Как выбрать строки из MySQL на основе максимального значения столбца + группировка

У меня есть таблица, которая содержит (допустим) все время, когда пользователь просматривал определенную веб-страницу. Конечно, пользователи могут просматривать страницу более одного раза, поэтому для пользователей и страниц может быть несколько записей:

nid     time    user  page_id
 25     8000       4      467
 24     7000       1      482
 23     6000       1      484
 22     5000       1      482
 21     4000       5      467
 20     3000       4      467

Я хочу сделать запрос, который возвращает строки, соответствующие каждой странице, просматриваемой каждым пользователем. С CATCH. Если пользователь просматривал страницу более одного раза, я получаю строку, соответствующую последнему виду (т.е. наибольшее значение TIME). Таким образом, я должен получить следующее:

nid     time    user  page_id
 25     8000       4      467
 24     7000       1      482
 23     6000       1      484
 21     4000       5      467

Мы теряем строку 22, потому что пользователь 1 посмотрел на страницу 482 позже, и мы теряем строку 20, потому что пользователь 4 посмотрел на страницу 467 позже.

Я почти понял это, но я не могу его взломать, а также убеждаю себя, что результаты, которые я получаю, будут в целом правильными, а не просто случайными случаями моих тестов. Я продолжаю идти туда и обратно между запросами GROUP BY или DISTINCT и встроенными запросами, а затем мой мозг взрывается. Какие-либо предложения? Спасибо!

Ответы

Ответ 1

Если вам нужна полная строка, вы можете использовать это:

SELECT fullTable.nid as nid, 
       recent.time as time, 
       fullTable.user as user, 
       fullTable.page_id as page_id 
  FROM TableName fullTable 
         INNER JOIN   (SELECT MAX(t1.time) as time, t1.user, t1.page_id 
                         FROM TableName t1 
                     GROUP BY user, page_id) recent
                 ON recent.time = fullTable.time AND 
                    recent.user = fullTable.user AND 
                    recent.page_id = fullTable.page_id
ORDER BY time DESC

Если вы запрашиваете столбец вне предложения "group by", mysql может вернуть любое значение для этого столбца внутри этой группы. Поэтому, если все значения внутри группы не совпадают, это ваш случай, вы не можете включить его непосредственно в предложение select, вам нужно использовать соединение.

Вы можете узнать больше о не сгруппированных столбцах в MySQL на ссылка

Если вам не нужно поле nid, вы можете использовать другое:

SELECT MAX(time) as time, user, page_id 
  FROM TableName
GROUP BY user, page_id
ORDER BY time DESC

Ответ 2

Попробуйте следующее:

SELECT *
  FROM <YOUR_TABLE>
 WHERE (user, page_id, time) IN
    (
    SELECT  user, page_id, MAX(time) time
      FROM <YOUR_TABLE>
    GROUP BY user, page_id
   )

Ответ 3

SELECT nid, MAX(time), user, page_id 
FROM TableName 
GROUP BY nid, user, page_id