I am using MySQL 8.0 version
I have a Result
table with columns of
id, playerId, groupId, position, timestamp
And I want to query a list of results on a specific player with unique groupId and position sorted in timestamp descending order. So within the same groupId, there could be multiple records of the same position, and I want to query only the latest record. So I think the key is to combine groupId and position for group by clause but I have no clue how to do that.
First, I tried...
SELECT * FROM Result
WHERE playerId = 15
GROUP BY groupId, position
ORDER BY timestamp DESC;
Got the following result.
> ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY
> clause and contains nonaggregated column 'Result.id' which is not
> functionally dependent on columns in GROUP BY clause; this is
> incompatible with sql_mode=only_full_group_by
So I tried...
SELECT *
FROM Result
WHERE id IN (
SELECT id
FROM Result
WHERE playerId = '15'
GROUP BY groupId
ORDER BY timestamp DESC
);
Got the following result.
+------+----------+----------+----------+---------------+
| id | playerId | groupId | position | timestamp |
+------+----------+----------+----------+---------------+
| 2634 | 15 | 237 | 1 | 1583703228386 |
| 2628 | 15 | 237 | 2 | 1583690801160 |
| 2627 | 15 | 237 | 1 | 1583690798117 |
| 2622 | 15 | 237 | 1 | 1583687601090 |
+------+----------+----------+----------+--------+-----+-
As you can see, there're groupId 237 with multiple of position 1. What I want is
+------+----------+----------+----------+---------------+
| id | playerId | groupId | position | timestamp |
+------+----------+----------+----------+---------------+
| 2634 | 15 | 237 | 1 | 1583703228386 |
| 2628 | 15 | 237 | 2 | 1583690801160 |
+------+----------+----------+----------+--------+-----+-
How do I do that?
With ROW_NUMBER() window function:
SELECT t.id, t.playerId, t.groupId, t.position, t.timestamp
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY position ORDER BY timestamp desc) rn
FROM Result
WHERE playerId = '15'
) t
WHERE t.rn = 1
If there are multiple different groupId
s for playerId = '15'
and you want 1 row for each combination of groupId, position
then:
SELECT t.id, t.playerId, t.groupId, t.position, t.timestamp
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY groupId, position ORDER BY timestamp desc) rn
FROM Result
WHERE playerId = '15'
) t
WHERE t.rn = 1