MySQL Как группировать, и показывать строку с наибольшим из указанного столбца для этой группы - PullRequest
0 голосов
/ 25 марта 2019

У меня есть следующая таблица в MySQL:

+-----------+------------+------------+------+-----------+
| user_name | session_id |   status   | data | timestamp |
+-----------+------------+------------+------+-----------+
| foo       |          1 | start      |    0 |       100 |
| foo       |          1 | checkpoint |   15 |       120 |
| foo       |          1 | stop       |   46 |       130 |
| foo       |          2 | start      |    0 |       200 |
| foo       |          2 | checkpoint |   97 |       210 |
+-----------+------------+------------+------+-----------+

Я пытаюсь выполнить запрос, который выбирает все поля из таблицы, сгруппированные по session_id, и результат которого отображается для одной группы какстрока с самой большой отметкой времени.

Вот что я придумала, она не выполняет свою работу, и я изо всех сил пытаюсь найти, куда идти отсюда:

select * from example where user_name = 'foo' and timestamp > 10 group by acct_session_id;

Этот оператор производит что-то вроде следующего:

+-----------+------------+------------+------+-----------+
| user_name | session_id |   status   | data | timestamp |
+-----------+------------+------------+------+-----------+
| foo       |          1 | checkpoint |   15 |       120 |
| foo       |          2 | start      |    0 |       200 |
+-----------+------------+------------+------+-----------+

То, что я хотел бы получить в результате:

+-----------+------------+------------+------+-----------+
| user_name | session_id |   status   | data | timestamp |
+-----------+------------+------------+------+-----------+
| foo       |          1 | stop       |   46 |       130 |
| foo       |          2 | checkpoint |   97 |       210 |
+-----------+------------+------------+------+-----------+

В этом примере строка с наибольшей отметкой времени была возвращена как 'top 'of the group.

Также, за любые предоставленные ответы, я был бы очень признателен за любые предложения относительно правильного индекса, чтобы этот оператор выполнялся максимально быстро.Я всегда пытался найти правильный индекс для сложного запроса, такого как этот.

* РЕДАКТИРОВАТЬ

Я прочитал ответы, найденные в теме, что эта тема была отмечена как дубликати попытался приспособить их к моему вопросу, но безуспешно.

Сначала я попробовал основной ответ из связанной ветки, изменив идентификаторы, чтобы они соответствовали моей таблице:

WITH ranked_messages AS (
  SELECT e.*, ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY timestamp DESC) AS rn
  FROM example AS e
)
SELECT * FROM ranked_messages WHERE rn = 1;

Я не имел успеха с этим, и в этот момент я очень смущен тем, что делает заявление.Итак, затем я посмотрел документацию для оконных функций здесь: https://dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html

Чтение этого не помогло так сильно, как я надеялся, но я вернулся к связанному потоку и попробовал несколько вещей.

Это самое близкое, что я получил:

SELECT e1.*
FROM example e1 LEFT JOIN example e2
 ON (e1.session_id = e2.session_id AND e1.timestamp < e2.timestamp)
WHERE e2.timestamp IS NULL and e1.user_name = 'foo';

В моей маленькой тестовой таблице это дало ожидаемый ответ, однако у меня только одно имя пользователя в этой таблице.Я не могу понять, как изменить этот запрос, чтобы искать только определенное имя пользователя, ДО того, как оно выполнит СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ, потому что в моей рабочей таблице у меня есть миллионы строк и тысячи имен пользователей, и я не могу выполнить этот запрос для каждого пользователя каждый раз.

...