MySQL группировка с упорядочиванием

Дмитрий
На сайте с 23.08.2006
Offline
222
7767

Помогите составить правильный запрос. Есть таблица `table_name`, в ней поля `id` (примари кей, автоинкремент, инт), `rubric_id` (инт) и `date` (дататайм). Много много записей с разными датами и иногда повторяющимися айдишниками рубрик (`rubric_id`).

Нужно выбрать по последней записи из каждой рубрики.

Вообщем получилось составить только такой запрос, но при большом количестве записей нехотелось бы так нагружать сервер.

SELECT * FROM (SELECT * FROM `table_name` ORDER BY `date` DESC) AS `Actions` GROUP BY `rubric_id` ORDER BY `date` DESC
Разрабатываю и автоматизирую на php http://jonnyb.ru/
V1
На сайте с 30.03.2006
Offline
52
#1

Зачем выбирать все из полученных данных ещё раз?

Правильно делать так:

select module_name, max(date_modified)

from tracker

group by module_name

P.S. имена подставить свои

Дмитрий
На сайте с 23.08.2006
Offline
222
#2

Vladimir1, пробывал так, вот результат выборки (первая запись):

date | MAX( `date` )

2008-11-02 15:01:16 | 2008-11-02 15:01:18

То есть еще одна колонка с максимальной дато появилась и все.. Так же пробывал с where `date`=MAX(`date`), ругается на неправильную конструкцию GROUP BY...

[Удален]
#3
JonnyB:
Vladimir1, пробывал так, вот результат выборки (первая запись):
date | MAX( `date` )
2008-11-02 15:01:16 | 2008-11-02 15:01:18

То есть еще одна колонка с максимальной дато появилась и все.. Так же пробывал с where `date`=MAX(`date`), ругается на неправильную конструкцию GROUP BY...

Он все правильно написал, первое поле есстественно должно быть не date, а то, что вам нужно. Там причем может быть много полей. Content или чего там у вас еще. Может вам просто id хватит

Дмитрий
На сайте с 23.08.2006
Offline
222
#4
neolord:
Он все правильно написал, первое поле есстественно должно быть не date, а то, что вам нужно. Там причем может быть много полей. Content или чего там у вас еще. Может вам просто id хватит

Мне нужна полная запись, а не только даты последних... То есть и id и contents и т.д...

А сейчас все что можно извлечь из этой выборки - id рубрики и дата последней принадлежащей ей записи.

[Удален]
#5
JonnyB:
Мне нужна полная запись, а не только даты последних... То есть и id и contents и т.д...
А сейчас все что можно извлечь из этой выборки - id рубрики и дата последней принадлежащей ей записи.

Боже ж ты мой. не думал что все настолько плохо...


SELECT *, max(date)
FROM table
GROUP BY `rubric_id`
Дмитрий
На сайте с 23.08.2006
Offline
222
#6

Может так попробую объяснить:

при выборке по этому запросу:

SELECT *,MAX(`date`) AS `lastdate` FROM `table_name` GROUP BY `rubric_id` ORDER BY `date` DESC

добавиться еще одна колонка к результатам этого:

SELECT * FROM `table_name` GROUP BY `rubric_id` ORDER BY `date` DESC

Причем `lastdate` с выборкой связывает только `rubic_id`, id, content и остальные поля не от записи с lastdate, а от записи date..

Я вас незапутал? :)

JonnyB добавил 06.11.2008 в 13:21

neolord, вы бы перед тем как такое писать попробывали бы....

JonnyB добавил 06.11.2008 в 13:27

Для чистоты эксперимента:

дампик таблицы

CREATE TABLE `test` (

`rubric_id` int(10) unsigned NOT NULL,
`date` datetime NOT NULL,
`content` text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `test` (`rubric_id`, `date`, `content`) VALUES
(1, '2008-11-06 12:00:00', 'Я запись от 2008-11-06 12:00:00'),
(1, '2008-11-06 11:00:00', 'А я запись от 2008-11-06 11:00:00'),
(2, '2008-11-06 12:30:00', 'Меня создали в 2008-11-06 12:30:00'),
(2, '2008-11-06 12:40:00', 'Я родился в 2008-11-06 12:40:00');

Наш запрос:

SELECT *, max(`date`)

FROM `test`
GROUP BY `rubric_id`

вернет следующую инфу:

rubric_id date content max( `date` )
1 2008-11-06 12:00:00 Я запись от 2008-11-06 12:00:00 2008-11-06 12:00:00
2 2008-11-06 12:30:00 Меня создали в 2008-11-06 12:30:00 2008-11-06 12:40:00

neolord, оно?

[Удален]
#7

Запутали по самое немогу =)

Видимо я так и не понял структуру вашей таблицы до конца. Без подзапроса вы в любом случае не обойдетесь из-за агрегатной функции, поэтому предлагаю такой вариант



SELECT * FROM `table` WHERE `date` IN
(SELECT max(`date`) FROM `table` GROUP BY `rubric_id`)
ORDER BY `date`

Проверил - работает, посмотрел explainом - вполне приемлимое быстродействие. К тому же подзапрос выполнится всего один раз а не при каждом проходе. Единственный косяк - если у вас поле "времядата" не уникально, т.е. несколько статей могу сразу быть добавлены, тогда так не получится - попадут лишние записи. Еще вариант - выбирать в подзапросе rubric_id, max(date) и сравнивать парами, но как это реализуется в MySQL не знаю.

Дмитрий
На сайте с 23.08.2006
Offline
222
#8

neolord, блин, вроде такая тривиальная задача, сделать сортировку перед группировкой :(

Всем спасибо, будем подзапросом делать...

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий