Как выбрать строки из 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