Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: GROUP BY в MySQL 5
 
 автор: Zmeonish   (19.03.2008 в 15:29)   письмо автору
 
 

Добрый день!

Столкнулся с проблемой группировки строк в результатах запроса - практика никак не стыкуется с теорией

есть тестовая таблица, 4 поля: автоинкриментный id, record, user, timeStamp

CREATE TABLE `test` (
`id` int(11) NOT NULL auto_increment,
`record` int(11) NOT NULL,
`user` int(11) NOT NULL,
`timeStamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 AUTO_INCREMENT=5 ;

INSERT INTO `test` (`id`, `record`, `user`, `timeStamp`) VALUES
(1, 1, 1, '2008-03-19 10:24:13'),
(2, 1, 2, '2008-03-19 10:24:41'),
(3, 2, 2, '2008-03-19 10:25:16'),
(4, 2, 1, '2008-03-19 10:25:26');

делаю простейшую выборку:

SELECT * FROM `test` GROUP BY record

получаю

id record user timeStamp
1 1 1 2008-03-19 10:24:13
3 2 2 2008-03-19 10:25:16

хотя ожидалось такое:

id record user timeStamp
1 1 1 2008-03-19 10:24:13
2 1 2 2008-03-19 10:24:41
3 2 2 2008-03-19 10:25:16
4 2 1 2008-03-19 10:25:26

на каком основании выкинуты строки 2 и 4 ? они должны входить в набор по условию GROUP BY, т.к. никаких функций группировки не задано

   
 
 автор: ronin80   (19.03.2008 в 16:09)   письмо автору
 
   для: Zmeonish   (19.03.2008 в 15:29)
 

всё логично, ты группируешь по полю record, а в нём всего два неповторяющихся значения 1 и2

   
 
 автор: Zmeonish   (19.03.2008 в 17:06)   письмо автору
 
   для: ronin80   (19.03.2008 в 16:09)
 

> всё логично, ты группируешь по полю record, а в нём всего два неповторяющихся значения 1 и2

нет, не логично, по стандарту SQL99, которому по идее должен следовать MySQL, выражение "GROUP BY" группирует строки по определенному полю, повторяю, группирует (собирает вместе) а не выбирает одни из них. Это еще как-то можно было понять если б строки были идентичные, но они неодинаковы!

на каком основании из 2 строк

1 1 1 2008-03-19 10:24:13
2 1 2 2008-03-19 10:24:41

была выбрана первая а не вторая?

если расширить условие выборки так, чтоб выбиралась самая "свежая" из 2 сгруппированных строк

SELECT id, record, user, MAX(timeStamp)
FROM `test`
GROUP BY record

id record user MAX(timeStamp)
1 1 1 2008-03-19 10:24:41
3 2 2 2008-03-19 10:25:26

то получается вообще каша - id, record и user будут от одной строки (id=1), а timeStamp - от другой (id=2)

   
 
 автор: barba   (20.03.2008 в 08:33)   письмо автору
 
   для: Zmeonish   (19.03.2008 в 17:06)
 

Тем не менее GROUP BY в MySQL используется именно для выборки уникальных значений, как и DISTINCT с некоторыми отличиями

   
 
 автор: Zmeonish   (20.03.2008 в 09:32)   письмо автору
 
   для: barba   (20.03.2008 в 08:33)
 

тогда переформулирую вопрос:

на каком основании при группировке строк по record

id record user timeStamp
1 1 1 2008-03-19 10:24:13
2 1 2 2008-03-19 10:24:41

выбирается первая строка

1 1 1 2008-03-19 10:24:13

как сделать так чтоб при группировке выбиралась строка с максимальным timeStamp ? Вариант с сортировкой по timeStamp и обрезанием вывода до 1 строки не предлагать, решить вопрос нужно именно с помощью группировки

   
 
 автор: Thrasher   (20.03.2008 в 10:13)   письмо автору
 
   для: Zmeonish   (20.03.2008 в 09:32)
 

Можно использовать вот такой извращённый способ:
SELECT * FROM
  (select * from `test` order by timeStamp desc)
GROUP BY record

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

   
 
 автор: barba   (20.03.2008 в 12:42)   письмо автору
 
   для: Zmeonish   (20.03.2008 в 09:32)
 

А подойдет ли вариант select (***) from (****) order by record, timeStamp desc; ?
На похожей таблице у меня работает вполне корректно

   
 
 автор: Obana   (19.03.2008 в 16:13)
 
   для: Zmeonish   (19.03.2008 в 15:29)
 

чтобы получить такой результат используй

SELECT * FROM `test` ORDER BY record

id record user timeStamp
1 1 1 2008-03-19 10:24:13
2 1 2 2008-03-19 10:24:41
3 2 2 2008-03-19 10:25:16
4 2 1 2008-03-19 10:25:26

   
 
 автор: Zmeonish   (19.03.2008 в 17:07)   письмо автору
 
   для: Obana   (19.03.2008 в 16:13)
 

мне нужно "приручить" GROUP BY

приведенный пример - сильно упрощенная модель реальной задачи, ORDER BY не подойдет

   
 
 автор: olejek   (20.03.2008 в 10:29)   письмо автору
 
   для: Zmeonish   (19.03.2008 в 17:07)
 

>мне нужно "приручить" GROUP BY
Примите его таким, какой он есть

>Можно использовать вот такой извращённый способ:
Зачем же извращаться. У меня, например, никогда не возникало проблем с запросами GROUP BY.
Zmeonish, а можете написать, что это за поле record (его функциональное назначение)?

   
 
 автор: Zmeonish   (20.03.2008 в 12:45)   письмо автору
 
   для: olejek   (20.03.2008 в 10:29)
 

таблица содержит лог обращений разных пользователей (user) к записям (record) другой таблицы

смысл задачи - вывести список записей, к которым обращались пользователи отсортировав их хронологически в обратном порядке

если к записи было несколько обращении - выводить только последнее

   
 
 автор: Thrasher   (20.03.2008 в 15:10)   письмо автору
 
   для: Zmeonish   (20.03.2008 в 12:45)
 

Ну так, мой запрос, написанный выше, для твоей задачи подходит.

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования