Задавайте вопросы, мы ответим
Вы не зашли.
Есть таблица с хитами (страницы, где был посетитель сайта). Нужно выбрать записи, где были посетители в последний раз за три минуты. Т.е., самую свежую запись для каждого посетителя, но не старее трех минут.
Фактически, алгоритм сводится к такому:
1. Отсеять за последние три минуты
2. Отсортировать по дате
3. Сгруппировать по юзерам
Но понятное дело, группировку в MySQL нельзя производить после сортировки... В мануале предлагается вариант типа
SELECT * FROM hits WHERE id IN (SELECT MAX(id) FROM hits WHERE adate>NOW()-INTERVAL 3 MINUTE GROUP BY user)
Это работает, но медленно. Есть конечно вариант с выборкой данных и последующим просчетом с помощью PHP (как оказалось, так быстрее), но, во-первых, интереснее сделать вчистую средствами MySQL, во-вторых, данных может быть много, в-третьих, просто некошерно как-то. Может быть можно сделать это с помощью процедур? Не приходилось с ними, к сожалению, работать, сложно самому судить об оптимальности такой реализации.
Как оптимизировать или сделать иначе?
Подскажите, пожалуйста.
Отредактированно bartwell (12.04.2010 16:48:21)
Неактивен
В мануале советуют все правильно, но в пятой версии неправильно работают подзапросы IN( .. GROUP BY). Подзапрос выполняется для каждой строки основного запроса. Есть несколько вариантов переписать запрос:
1) сделать в несколько этапов:
а) выбрать max(id) во временную таблицу
б) выбрать всю нужную инфу по найденым id
в) удалить временную таблицу
2) Переписать хитрым образом типа
SELECT substr(MAX(CONCAT(id,username)),-40) as username FROM hits WHERE adate>NOW()-INTERVAL 3 MINUTE GROUP BY user;
Тогда другие поля (в данном примере username) будут выбраны соответствующими максимальному id. В данном примере предполагается, что username имеет тип char(40).
3) переписать через JOIN имея подзапрос в части FROM.
Неактивен
vasya, большое спасибо за подробный ответ. Именно этой информации и не хватало
Неактивен