Reputation: 1729
Let's assume that I have a table (myTable) with 4 columns (id, player_id, myDate, points). I want to find the points that all players had on a certain day
id | player_id | myDate | points
------ | --------- | ---------- | -----
1 | 1 | 2016-05-06 | 50
2 | 1 | 2016-10-16 | 60
3 | 1 | 2016-09-12 | 70
4 | 1 | 2016-09-16 | 30
5 | 2 | 2016-02-05 | 10
6 | 2 | 2016-10-18 | 20
7 | 2 | 2017-01-02 | 30
8 | 2 | 2016-08-16 | 40
Expected result for 1/1/2017:
id | player_id | myDate | points
------ | --------- | ---------- | -----
2 | 1 | 2016-10-16 | 60
6 | 2 | 2016-10-18 | 20
What I would do until now is something like the following: (first find the last date of each player and then the score of that date)
select id, q.player_id, points from
(
select player_id, max(myDate) as maxDate from myTable
where myDate<'2017-01-01'
group by player_id
) q
left join myTable
on q.maxDate=myTable.mydate
and q.player_id=myTable.player_id
Of course, in case I have 2 records of the same player on the same date, I would get 2 rows for this player_id and I would have to add more code to the query to solve this problem.
Apart from that I have to self join (my table has 1.000.000 records at the moment - tbh it's a view) and this could not be fast.
I have lately been using another query:
select id,player_id,points from
(
select rank() over
(partition by player_id
order by myDate desc, id desc) as r, *
from myTable
where myDate <'2017-01-01'
) q
where r=1
Is there a better (= more efficient) way to achieve what I want?
Upvotes: 0
Views: 36
Reputation: 121524
Use DISTINCT ON
.
select distinct on (player_id) *
from my_table
where my_date < '2017-01-01'
order by player_id, my_date desc;
Upvotes: 1