Group by doesn't work (SELECT list is not in GROUP BY clause and contains nonaggregated column)

KoreanDude :

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?

forpas :

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 groupIds 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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=171085&siteId=1