Reputation: 69
I have a table called scores. id is the auto-incremented primary key.
id | player_id | score |
---|---|---|
1 | 1 | 100 |
2 | 1 | 57 |
3 | 2 | 434 |
4 | 3 | 11 |
5 | 3 | 132 |
6 | 4 | 32 |
7 | 4 | 100 |
8 | 4 | 21 |
Given a list of player ids, I need to return the last score received from each player_id in the list (i.e. the score that has the greatest id with the given player_id).
Using the data above, player 1 should return 57, player 2 should return 434, player 3 should return 132, and player 41 should return 21.
Let's say I am given a list containing player_ids 3 and 4. I want to create a single query that returns 132 for the first row and 21 for the second row.
The individual queries would be
select score from scores where player_id = 3 order by id desc limit 1;
select score from scores where player_id = 4 order by id desc limit 1;
I'm having trouble combining these two into one query. I want to avoid using UNION because the list could contain hundreds of player_ids.
Upvotes: 0
Views: 92
Reputation: 1075
You can use NOT EXISTS
as follows:
select t.id, t.player_id, t.score
from scores t
where not exists (select 1 from scores tt
where tt.player_id = t.player_id
and tt.id > t.id);
Another option is to use ROW_NUMBER
window function as follows:
select t.id, t.player_id, t.score from
(select t.id, t.player_id, t.score,
row_number() over (partition by t.player_id order by t.id desc) as rn
from scores t) t
where rn = 1;
NOTE: You can add one more condition in WHERE
clause to include only required player_id
like player_id in (3,4)
Upvotes: 0
Reputation: 601
You could get desired result from multiple approach.
Approach 1
SELECT *
FROM Scores
WHERE id IN (
SELECT Max(id)
FROM scores
GROUP BY player_id
)
In this approach, sub-query SELECT Max(id) FROM scores GROUP BY player_id
gets the greatest/max id
for each player_id
. And gets result on the basis of those id.
Approach 2
SELECT s.player_id
,s.id
,s.score
FROM scores s
JOIN (
SELECT player_id
,MAX(id) AS max_id
FROM scores
GROUP BY player_id
) t ON s.player_id = t.player_id
AND s.id = t.max_id;
In this apporoach, sub-query is quite similar to above one but it additionally returns player_id
also which is used for joining to retrive the data.
Upvotes: 1