Xpoint
   [напомнить пароль]

Запрос с соритровкой по одному полю и группировкой по другому

Метки: [без меток]
2007-11-07 23:11:23 [обр] Антон(0/3)[досье]
Возможно я туплю, т.к. задача вроде бы довольно банальна, но нарисовать запрос самостоятельно как-то не получилось.
А ситуация такова: в таблице есть поле, к примеру, "name" и поле "date". Может быть много записей с одинаковым значением "name" и разными "date". Необходимо выбрать строго N записей с наиболее свежей "date" для уникальных "name". Т.е. если несколько самых свежих записей имеют одинаковый "name" из них нужна одна самая свежая, потом самая свежая с другим "name" и таких N записей отсортированных by `date` desc...
Вот, может быть несколько сумбурно, но что-то к вечеру соображаю уже совсем туго...
спустя 2 часа 25 минут [обр] Дмитрий Попов(17/509)[досье]
Группировка в любом случае выполняется до ордера. Боюсь надежного решения с одним простым запросом (без джойнов или вложенных запросов) не получится...
спустя 13 минут [обр] Алексей Севрюков(7/1292)[досье]

Разве простой SELECT name, MAX(date) GROUP BY name ORDER BY MAX(date) DESC LIMIT 10 (для MySQL) не поможет?

P.S. Засыпаю, так что может и глупость написал.

спустя 11 часов [обр] Антон(0/3)[досье]
Алексей Севрюков[досье]
В частном случае да, все работает правильно, но, видимо я слишком минимизировал задачу. Как только появляется необходимость выбрать из этой таблицы не только data и name, а допустим еще некие поля text и id, то они берутся не от той записи где MAX(date) а как бог на душу ляжет...
спустя 38 минут [обр] Алексей Севрюков(7/1292)[досье]
Антон[досье] В этом случае как было сказано выше уже нужны джойны или вложенные запросы.
спустя 3 часа 53 минуты [обр] Антон(0/3)[досье]
Алексей Севрюков[досье] Повидимому вы правы... Просто я надеялся что это не окончательный приговор (т.к. не получилось у меня ни с джоинами ни с вложенными запросами...)
спустя 5 часов [обр] Алексей Севрюков(7/1292)[досье]
А что из себя представляет id? Может он у Вас AUTO_INCREMENT и если строчки вставляются в порядке очередности дат, то можно попробовать привязаться к этому id. Вообщем дайте пример таблице, а то так не думается совсем.
спустя 13 минут [обр] Алексей Севрюков(7/1292)[досье]

Вообщем время позднее, я табличку создал, и по Вашим условия попытался что-то сделать. Получилось вот что:

SELECT a.*
FROM `test` a
WHERE a.tdate = (
  SELECT MAX( b.tdate )
  FROM test b
  WHERE a.name = b.name
  GROUP BY b.name
 )
ORDER BY a.tdate DESC 
LIMIT 10

Я не стал очень уж много строчек заводить, штук 10 сделал, вроде все правильно.
Вообщем попробуйте и проверьте результат.
P.S. Нужен MySQL 4.1+

спустя 3 минуты [обр] Алексей Севрюков(7/1292)[досье]
Вообщем я глупость написал кажется )) Завтра еще подумаю.
спустя 46 минут [обр] Алексей Севрюков(7/1292)[досье]

О, MySQL позволяет делать такое:

SELECT a . *
FROM `test` a
WHERE (a.tdate, a.name) = (
SELECT MAX( b.tdate ) , b.name
FROM test b
WHERE a.name = b.name
GROUP BY b.name )
ORDER BY a.tdate DESC

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

P.S. Мануал рулит )

спустя 8 часов [обр] Lynn «Кофеман»(0/571)[досье]
спустя 43 минуты [обр] Антон(0/3)[досье]
Алексей Севрюков[досье]О! последний запрос просто супер... Вот уж действительно не знал что можно так where (x,y)=(...,...) - век живи век учись... Спасибо большое. А насчет автоинкрементного id да, мысль верная (и я так раньше и выкручивался :)), вот только дата не всегда есть дата создания записи...
Lynn «Кофеман»[досье]о, тоже то что надо, да еще и под третьим заработает если что.
спустя 1 час 30 минут [обр] Алексей Севрюков(7/1292)[досье]
Lynn «Кофеман»[досье] не, я такое не потяну. Я сейчас смотрю и искренне не понимаю как тот запрос работает.
спустя 2 часа 4 минуты [обр] Антон(0/3)[досье]
Алексей Севрюков[досье]Да ну :). Он таблицу саму с собой объединяет причем по условию где "дата больше" и выбирает те поля, где это условие не сработало и получился NULL (т.е. где дата самая большая и больше нее нет). Там надо поставить не t1.* а просто * и убрать условие где IS NULL и все сразу станет понятно.
спустя 1 час 30 минут [обр] Алексей Севрюков(7/1292)[досье]
Антон[досье] ну я примерно так и предполагал. Но я совершенно не скрываю и не стесняюсь того что в SQL я чайник, хотя работаю с ним достаточно постоянно.
Кстати интересно что будет быстрее. По идее объединение.
спустя 20 минут [обр] Антон(0/3)[досье]
Алексей Севрюков[досье]Ну тогда я мегачайник :). А в тестах на скорость я хоть не силен, но SQLFront показал, что объединение несколько быстрее (хотя тут тоже наверняка есть масса нюансов).
Powered by POEM™ Engine Copyright © 2002-2005