RSS
 

GROUP BY

Выбор нужной строки среди группируемых.

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

Есть таблица MySQL
rel_id, date, extra_data

PRIMARY (date, extra_data)
rel_id - неукален

Задача выбрать самый свежий экземпляр extra_data для каждого rel_id

Интерес заключался в том, чтобы найти эти данные без подзапроса или join-ов. Иначе задача становится довольно тривиальной.
Почитав документацию (http://dev.mysql.com/tech-resources/articles/debunking-group-by-myths.html), погуглив и выполнив другие предписуемые ритуалы - мы пришли к выводу, что сделать это не удастся и нужно будет воспользоваться каким-нибудь из следующих вариантов:

SELECT `tbl`.`extra_data` FROM
 `tbl` INNER JOIN (
    SELECT MAX(`date`) AS `date`, `rel_id` FROM `tbl` GROUP BY `rel_id`
  ) AS `tnp_tbl`
  USING (`rel_id`, `date`)

SELECT * FROM tbl WHERE (rel_id, DATE) IN (SELECT rel_id, MAX(DATE) FROM tbl GROUP BY rel_id)

Еще был такой вариант, но он не годился, из-за того, что GROUP BY не гарантирует какой из рядов внутри группы он возьмет.
SELECT * FROM (SELECT * FROM `table` ORDER BY `date` DESC) `tbl` GROUP BY rel_id

Учитывая все это, надеясь на авось, вчера вечером решил еще адресовать вопрос одному знакомому SQL-щику. Вдруг мы что-то упустили?!
Задачу поставил так: выбрать нужные строки без исползований джойнов и подзапросов. И мы таки кое-что упустили:

SELECT rel_id,MAX (CONVERT ([DATE], 121) + extra_data) 
FROM myTable
GROUP BY rel_id
Это код для MsSQL, но под мускуль его портировать довольно несложно. Идея заключается в том, чтобы соединить поле даты и данных, как строки. А потом выбрать максимальную вновь-образованную строку.