Группировка по не работает (список SELECT отсутствует в предложении GROUP BY и содержит неагрегированный столбец) - PullRequest
0 голосов
/ 09 марта 2020

Я использую MySQL 8.0 версию

У меня есть Result таблица со столбцами

id, playerId, groupId, position, timestamp

И я хочу запросить список результатов по конкретному c игрок с уникальным идентификатором группы и позицией, отсортированной по убыванию отметки времени. Таким образом, в одном и том же groupId может быть несколько записей одной и той же позиции, и я хочу запросить только самую последнюю запись. Поэтому я думаю, что ключ в том, чтобы объединить groupId и position для group by, но я понятия не имею, как это сделать.

Сначала я попытался ...

SELECT * FROM Result
WHERE playerId = 15
GROUP BY groupId, position
ORDER BY timestamp DESC;

Получил следующее результат.

> 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

Итак, я попытался ...

SELECT *
FROM Result
WHERE id IN (
    SELECT id
    FROM Result
    WHERE playerId = '15'
    GROUP BY groupId
    ORDER BY timestamp DESC
);

Получил следующий результат.

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

Как видите, есть groupId 237 с кратным положением 1. То, что я хочу, это

+------+----------+----------+----------+---------------+
| id   | playerId |  groupId | position | timestamp     | 
+------+----------+----------+----------+---------------+
| 2634 |     15   |      237 |        1 | 1583703228386 |
| 2628 |     15   |      237 |        2 | 1583690801160 |
+------+----------+----------+----------+--------+-----+-

Как мне это сделать?

Ответы [ 2 ]

0 голосов
/ 09 марта 2020

С оконной функцией ROW_NUMBER ():

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

Если есть несколько различных groupId s для playerId = '15', и вы хотите по 1 строке для каждой комбинации groupId, position, тогда:

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
0 голосов
/ 09 марта 2020

Предполагая, что временные метки являются уникальными в вашем случае, я бы предложил что-то вроде этого:

SELECT r.*
FROM 
(SELECT groupId, position, MAX(timestamp) as lastTimestamp
FROM Result
GROUP BY groupId, position) as lastResults
LEFT JOIN Result r
ON lastResults.groupId = r.groupId 
AND lastResults.position = r.position
AND lastResults.lastTimestamp = r.timestamp;

Хитрость заключается в том, чтобы сначала идентифицировать уникальные составные ключи для необходимых вам данных (groupId, position, MAX(timestamp)), а затем выберите данные на основе этих ключей.

Если временные метки не являются уникальными, то вам нужно решить, какую строку выбрать, основываясь на любых бизнес-требованиях, которые у вас есть. Мой запрос в этом случае вернет повторяющиеся строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...