Table:
UserId, Value, Date.
I want to get the UserId, Value for the max(Date) for each UserId. That is, the Value for each UserId that has the latest date. Is there a way to do this simply in SQL? (Preferably Oracle)
Update: Apologies for any ambiguity: I need to get ALL the UserIds. But for each UserId, only that row where that user has the latest date.
I think something like this. (Forgive me for any syntax mistakes; I'm used to using HQL at this point!)
EDIT: Also misread the question! Corrected the query...
This will retrieve all rows for which the my_date column value is equal to the maximum value of my_date for that userid. This may retrieve multiple rows for the userid where the maximum date is on multiple rows.
"Analytic functions rock"
Edit: With regard to the first comment ...
"using analytic queries and a self-join defeats the purpose of analytic queries"
There is no self-join in this code. There is instead a predicate placed on the result of the inline view that contains the analytic function -- a very different matter, and completely standard practice.
"The default window in Oracle is from the first row in the partition to the current one"
The windowing clause is only applicable in the presence of the order by clause. With no order by clause, no windowing clause is applied by default and none can be explicitly specified.
The code works.
In
Oracle 12c+
, you can use Top n queries along with analytic functionrank
to achieve this very concisely without subqueries:The above returns all the rows with max my_date per user.
If you want only one row with max date, then replace the
rank
withrow_number
:i thing you shuold make this variant to previous query:
I think this should work?
Just had to write a "live" example at work :)
This one supports multiple values for UserId on the same date.
Columns: UserId, Value, Date
You can use FIRST_VALUE instead of MAX and look it up in the explain plan. I didn't have the time to play with it.
Of course, if searching through huge tables, it's probably better if you use FULL hints in your query.