2

I have an Azure Cosmos DB that contains columns DateTime, userName, temperature, and bloodPressure, plus many other columns. There are several distinct userName values, and each userName has temperature and bloodPressure data collected at different values of DateTime. The temperature and bloodPressure values are different for each of those 15 times.

Here is an example of the data,

userName, DateTime, bloodPressure, temperature, heartBeat, hatSize
Curly, "2021-01-19 18:24:53", 121, 98, 60, 7.25
Larry, "2021-01-14 18:24:53", 125, 99, 80, 7.5
Mo, "2021-01-13 18:24:53", 123, 100, 70, 7.75
Curly, "2021-01-18 18:24:53", 120, 97, 50, 8
Larry, "2021-01-13 18:24:53", 119, 99, 75, 7.15
Larry, "2021-01-15 18:24:53", 115, 98, 85, 7.37
Mo, "2021-01-12 18:24:53", 110, 102, 100, 8.01
Mo, "2021-01-20 18:24:53", 130, 99, 110, 6.97
Larry, "2021-01-18 18:24:53", 127, 98, 72, 7.76
Curly, "2021-01-17 18:24:53", 126, 97, 82, 8.0

For each user, I would like to return the DateTime of their latest measurement, and their temperature and bloodPressure from their latest DateTime:

Larry, "2021-01-18 18:24:53", 127, 98
Mo, "2021-01-20 18:24:53", 130, 99
Curly, "2021-01-19 18:24:53", 121, 98

I tried this,

SELECT  
    c.userName,
    MAX(c.DateTime),
    c.bloodPressure, 
    c.temperature
FROM CheckupData c
GROUP BY 
    c.userName

but got an error that GROUP BY should include the other outputs of SELECT. Since bloodPressure and temperature are always changing, it seems like I shouldn't use them in GROUP BY, because I only want the lastest values. What am I doing wrong? (If it matters, my real database is larger: 50,000 userNames measured at 50 or so DateTime values each, and 30 or so columns).

3
  • 1
    If CosmosDB doesn't have window functions, then you want greatest-n-per-group - if user_name is a PK, then you should be able to SELECT c.user_name, MAX(c.date_time) AS mdt FROM checkup_data c GROUP BY c.user_name and then join that back to checkup_data on the PK and mdt - taking the bp and temp... I did something like this today here - there's links within also.
    – Vérace
    Apr 8, 2021 at 19:42
  • 1
    I threw together this - if no window functions are available...
    – Vérace
    Apr 8, 2021 at 20:09
  • Thanks Verace. I think JOIN ON is different for Azure Cosmos. This example only has JOIN IN. I will try to adapt your code.
    – KAE
    Apr 9, 2021 at 15:27

2 Answers 2

1

I don't have an environment to test with, but the below might work for you.

EDIT: I see now that this is the same approach as @Verace's comment, but still, it should work in Cosmos DB.

https://learn.microsoft.com/en-us/azure/cosmos-db/sql-query-subquery

SELECT c.userName
    , c.DateTime 
    , c.bloodPressure
    , c.temperature
FROM CheckupData c
    JOIN  (SELECT g.userName, MAX(g.DateTime) AS MaxDateTime FROM CheckupData g GROUP BY g.userName) m
WHERE m.userName = c.userName 
    AND m.MaxDateTime = c.DateTime 
1
  • When I tried this query in the Cosmos portal it said "We have detected you may be using a subquery. Non-correlated subqueries are not currently supported. Please see Cosmos sub query documentation for further information". When I ran the query, I got the error "Identifier CheckupData could not be resolved." Here is some info on that that I will look at.
    – KAE
    Apr 9, 2021 at 14:57
0

EVERY Column in a SELECT has to be in the GROUP BY or use a aggregator function

SELECT  
    c.userName,
    MAX(c.DateTime),
    c.bloodPressure, 
    c.temperature
FROM CheckupData c
GROUP BY 
    c.userName,c.bloodPressure, c.temperature

OR

SELECT  
    c.userName,
    MAX(c.DateTime),
    AVG(c.bloodPressure), 
    AVG(c.temperature)
FROM CheckupData c
GROUP BY 
    c.userName

As we don't know nothing about your data and desired result. You have to choose what values you need.

For big tables you can use

CREATE TABLE CheckupData 
    ([userName] varchar(5), [DateTime] varchar(21), [bloodPressure] int, [temperature] int, [heartBeat] int, [hatSize] int)
;
    
INSERT INTO CheckupData 
    ([userName], [DateTime], [bloodPressure], [temperature], [heartBeat], [hatSize])
VALUES
    ('Curly', '"2021-01-19 18:24:53"', 121, 98, 60, 7.25),
    ('Larry', '"2021-01-14 18:24:53"', 125, 99, 80, 7.5),
    ('Mo', '"2021-01-13 18:24:53"', 123, 100, 70, 7.75),
    ('Curly', '"2021-01-18 18:24:53"', 120, 97, 50, 8),
    ('Larry', '"2021-01-13 18:24:53"', 119, 99, 75, 7.15),
    ('Larry', '"2021-01-15 18:24:53"', 115, 98, 85, 7.37),
    ('Mo', '"2021-01-12 18:24:53"', 110, 102, 100, 8.01),
    ('Mo', '"2021-01-20 18:24:53"', 130, 99, 110, 6.97),
    ('Larry', '"2021-01-18 18:24:53"', 127, 98, 72, 7.76),
    ('Curly', '"2021-01-17 18:24:53"', 126, 97, 82, 8.0)
;
GO
SELECT
cd.[userName], cd.[DateTime], cd.[bloodPressure], cd.[temperature], cd.[heartBeat], cd.[hatSize]
FROM CheckupData cd INNER JOIN 
(SELECT MAX([DateTime]) lastdate,[userName] FROM CheckupData GROUP BY [userName]) cd1
ON cd.[userName]  = cd1.[userName] AND cd.[DateTime] = cd1.lastdate
GO
userName | DateTime              | bloodPressure | temperature | heartBeat | hatSize
:------- | :-------------------- | ------------: | ----------: | --------: | ------:
Mo       | "2021-01-20 18:24:53" |           130 |          99 |       110 |       6
Larry    | "2021-01-18 18:24:53" |           127 |          98 |        72 |       7
Curly    | "2021-01-19 18:24:53" |           121 |          98 |        60 |       7

db<>fiddle here

11
  • I added example data to my question, thanks for pointing out that was needed. Is there an aggregator function instead of AVG that will find the bloodPressure and temperature value that was measured at the MAX(c.DateTime) for each user?
    – KAE
    Apr 9, 2021 at 12:45
  • @KAE i added a query for your question.
    – nbk
    Apr 9, 2021 at 17:22
  • Thanks so much. Unfortunately it seems like Cosmos DB doesn't allow INNER JOIN, or the square bracket convention like cd.[userName]. It is really hard to figure out how to write a complicated Cosmos DB query that works since it's using its own flavor of SQL. I may just dump all the data out and do it by brute force.
    – KAE
    Apr 16, 2021 at 21:25
  • There is a SQL query test tool for Azure Cosmos DB here that seems useful for learning it, so I'll see if that helps.
    – KAE
    Apr 16, 2021 at 21:37
  • 1
    you can use simokly join the inner is implicit and remove the brackets
    – nbk
    Apr 16, 2021 at 21:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.