MySQL -> использование order после group @ DeForum.ru
DeДверь  
Логин:  
Пароль:  
  Автологин  
   
Разместить рекламу
Письмо админу
Правила | FAQ | *Поиск | Наша команда | Регистрация | Вход
 
 
 Страница 1 из 1 [ Сообщений: 19 ] 
*   Список форумов / Начинка и техника / Программирование для WWW » ответить » создать топик « | »
Автор Сообщение
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Заголовок сообщения: MySQL -> использование order после group
Сообщение Добавлено: 19 Февраль 2008, 17:38:02 
Предположим, мне необходимо для каждого пользователя получить из базы один его последний комментарий. Как это сделать рациональным способом?

Я делаю так (о, ужас!):
Код:
select *
from (
    select users.user, comments.comment, comments.comment_date
    from users, comments
    where users.id = comments.user_id
    order by comments.comment_date desc
) c
group by c.id
order by c.comment_date desc


Наверняка кто-то уже сталкивался с проблемой group by + order :confused:

_________________
{'L'}('J')
Кухан Муж.
соучастник
18
Сообщения: 581
Зарегистрирован: 20.06.05
Откуда: МОСКВА
Сообщение Добавлено: 19 Февраль 2008, 18:09:30 
как-то сложно слишком
неужели не работает DISTINCT по автору и сортировка комментариев в обратном порядке?

_________________
Какая-то реклама — «HTML» вёрстка.
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 19 Февраль 2008, 18:19:29 
Арт Директор, order by имеет смысл ТОЛЬКО по тем полям, которые перечислены в group by.

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

P.S. "select *" в сочетании с group by также признак того, что ты не понимаешь, что делаешь. Ни одна полноценная БД этот бред не пропустит, а MySQL вернет бредовый ответ.
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Сообщение Добавлено: 19 Февраль 2008, 19:06:03 

Crazy писал(а):
Арт Директор, order by имеет смысл ТОЛЬКО по тем полям, которые перечислены в group by.

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

P.S. "select *" в сочетании с group by также признак того, что ты не понимаешь, что делаешь. Ни одна полноценная БД этот бред не пропустит, а MySQL вернет бредовый ответ.



Я ж по-русски, вроде, написал: мне необходимо для каждого пользователя получить из базы один его последний комментарий. Плюс имя самого пользователя из users.
В таблице comments находится множество комментариев для каждого пользователя из таблицы users. Поэтому нужно какую-то группирующую функцию применять (MAX(), DISTINCT()) или GROUP BY

Я не спорю, что не понимаю, что делаю. Понимал бы, не спрашивал.
Но задача, для человеческой логики, тривиальная. Не пойму, почему в имплементации БД все так усложняется?.. :insane:

Ты вот если понимаешь, так подскажи! :genius:



Кухан писал(а):
как-то сложно слишком
неужели не работает DISTINCT по автору и сортировка комментариев в обратном порядке?



DISTINCT по users.user отменяет сортировку по comments.comment_date :fie:

_________________
{'L'}('J')
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 19 Февраль 2008, 19:23:12 

Цитата:
задача, для человеческой логики, тривиальная



Согласно тривиальной человеческой логике запрос про "последний комментарий" должен содержать функцию MAX. Чего в первом запросе я не вижу.


Цитата:
Не пойму, почему в имплементации БД все так усложняется?



Если ты мыслишь в терминах множеств, ;) то ничто не усложняется.

Начнем с простого: что должен вывести запрос, если у пользователя 3 (три) комментария с равной максимальной датой?
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Сообщение Добавлено: 19 Февраль 2008, 19:38:16 

Crazy писал(а):

Цитата:
задача, для человеческой логики, тривиальная



Согласно тривиальной человеческой логике запрос про "последний комментарий" должен содержать функцию MAX. Чего в первом запросе я не вижу.



Эх, если бы все так просто было...

Код:
--
-- Структура таблицы `test_users`
--

CREATE TABLE `test_users` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(20) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=3 ;

--
-- Дамп данных таблицы `test_users`
--

INSERT INTO `test_users` (`id`, `name`) VALUES
(1, 'Вася'),
(2, 'Петя');



--
-- Структура таблицы `test_comments`
--

CREATE TABLE `test_comments` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `user_id` int(10) unsigned NOT NULL default '0',
  `comment` varchar(30) NOT NULL default '',
  `comment_date` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=7 ;

--
-- Дамп данных таблицы `test_comments`
--

INSERT INTO `test_comments` (`id`, `user_id`, `comment`, `comment_date`) VALUES
(1, 1, 'Первый комментарий', '2008-02-19 19:29:09'),
(2, 2, 'Первый комментарий', '2008-02-19 19:29:09'),
(3, 1, 'Второй комментарий', '2008-02-19 19:29:24'),
(4, 2, 'Второй комментарий', '2008-02-19 19:29:24'),
(5, 1, 'Третий комментарий', '2008-02-19 19:29:40'),
(6, 2, 'Третий комментарий', '2008-02-19 19:29:40');



А вот запрос:

Код:

SELECT max( comment_date ) AS date, name,
COMMENT FROM test_users, test_comments
WHERE test_users.id = user_id
GROUP BY test_users.id



Ну а вот и ответ:

Код:
2008-02-19 19:29:40   Вася       Первый комментарий
2008-02-19 19:29:40   Петя       Первый комментарий


Тут нельзя обойтись без GROUP BY(), которому плевать на твой MAX()

А ведь мне нужен ТРЕТИЙ комментарий для каждого пользователя.
Можешь написать запрос? :confused:

_________________
{'L'}('J')
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 19 Февраль 2008, 19:59:40 
Арт Директор, ты продолжаешь буйно фантазировать вместо того, чтобы ответить на заданный тебе вопрос.

Во-первых, max прекрасно работает с group by. Строго по книжкам уровня "SQL для чайников". Правда, ты их не читал.

Во-вторых, в тех же книжках написано, что при использовании group by в select'е можно перечислять только колонки, упомянутые в group by и аггрегатные фунции (max, min, avg и т.п.). Запрос, нарушающий эти правила, в случае MySQL будет возращать некоторые произвольные данные. Что мы и наблюдаем.

Итак, я повторяю вопрос: что должен вывести запрос, если у пользователя 3 (три) комментария с равной максимальной датой?
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 19 Февраль 2008, 20:24:12 
Для экономии времени: очевидно, что получить список дат последних комментариев совсем нетрудно:

Код:
select user_id, max(comment_date) as recent_comment_date from test_comments group by user_id


Также очевидно, что если бы у нас была таблица recents с колонками user_id и recent_comment_date, то получить список последних комментариев тоже было бы нетрудно:

Код:
select * from recents r join test_comments c on r.recent_comment_date = c.comment_date and r.user_id = c.user_id;


Вот только... мы возвращаемся к вопросу, который я задал выше.
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Сообщение Добавлено: 19 Февраль 2008, 20:28:06 

Crazy писал(а):
Итак, я повторяю вопрос: что должен вывести запрос, если у пользователя 3 (три) комментария с равной максимальной датой?



Это самая смехотворная "проблема" :killanasshole:
Можно сортировать по test_comments.id desc, который уникален. Вопрос отпал.

_________________
{'L'}('J')
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Сообщение Добавлено: 19 Февраль 2008, 20:37:11 
Еще одну таблицу создать - это не очень-то похоже на оптимизацию. Из одного обращения к базе мы получим два? или три?…
И потом, теперь надо не только писать коммент в comments, но еще и апдейтить recent. Накрутил пуще прежнего...

Одним запросом можешь?

_________________
{'L'}('J')


Последний раз редактировалось Арт Директор 19 Февраль 2008, 20:38:02, всего редактировалось 1 раз.
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 19 Февраль 2008, 20:37:32 

Арт Директор писал(а):
Это самая смехотворная "проблема" :killanasshole:



Когда сайт из-за смехотворных проблем принимает смехотворный вид -- лично мне становится смешно. Поскольку это всегда не мои сайты.


Цитата:
Можно сортировать по test_comments.id desc, который уникален. Вопрос отпал.



Эта фраза очень хорошо иллюстрирует причину, по которой написание запросов для БД кажется тебе запутанным делом.

Вопрос был -- как оставить один из N. Ты предложил отсортировать. Отлично. Вот только количество от этого не изменилось. Если бы ты обращал внимание на то, как твои ответы соотносятся с вопросами -- БД было бы легче тебя понимать.

Итак, мы имеем:

1. Два компонента запроса, которые я написал выше.
2. Твое предложение о сортировке.

Отлично. Преврати п.2. в выражение для выделение одной строки из N и соедини с двумя моими фрагментами. И будет тебе счастье.


Цитата:
можешь лаконичный запрос написать



Я -- могу. Более того, он у меня написан и проверен. Ну ты же не думал, что я тебе его дам? :lol:


Цитата:
ли так и будешь повторять то, что и так написано в онлайн-документации?



Ну что ж еще делать, если ты не в состоянии сам ее прочитать? :) Кто ж еще выполнит эту гуманитарную миссию?
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 19 Февраль 2008, 20:38:21 

Арт Директор писал(а):
Еще одну таблицу создать - это не очень-то похоже на оптимизацию.



А что, я где-то предложил создавать таблицу? Читаем внимательнее.
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Сообщение Добавлено: 19 Февраль 2008, 20:41:20 

Crazy писал(а):
Ну ты же не думал, что я тебе его дам? :lol:



Ваще-то думал. Иначе не стал бы ввязываться в пустую полемику.

Я ведь могу сказать, что одним словом могу написать этот запрос. Просто тебе показывать не хотел, поэтому предложил создать парутаблиц и сделать несколько обращений к базе вместо одного :lol: :lol: :lol:

_________________
{'L'}('J')
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 19 Февраль 2008, 20:49:20 

Арт Директор писал(а):
Я ведь могу сказать, что одним словом могу написать этот запрос.



Можешь. Разница в том, что мне поверят все, а тебе -- никто. :) Так что практической пользы, акромя конфуза, это не принесет.

Ну и последний hint: ты допустил принципиальную ошибку в условии задачи. Твоя постановка вопроса:


Цитата:
необходимо для каждого пользователя получить из базы один его последний комментарий



Это -- сферический конь вакууме. А вот почти то же самое, но приближенное к реальности:


Цитата:
Необходимо на странице вывести список пользователей, показав для каждого его последний комментарий (или пустую строку, если комментариев не было)



Юмор ситуации в том, что это совсем разные задачи. Вторая решается заметно проще, чем первая.

Удачи! :)
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Сообщение Добавлено: 19 Февраль 2008, 23:02:30 

Crazy писал(а):
Можешь. Разница в том, что мне поверят все, а тебе -- никто. :)



Я-то пост начал с работающего запроса, а ты просто зафлудил тему болтовней.

Пожалуй, и закончу его работающим запросом.
Код:
select name, t1.comment
from test_users, test_comments t1
left join test_comments t2 on t1.comment_date < t2.comment_date
where t2.comment_date is null
and t1.user_id = test_users.id

_________________
{'L'}('J')
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 19 Февраль 2008, 23:51:36 

Арт Директор писал(а):
Я-то пост начал с работающего запроса, а ты просто зафлудил тему болтовней.



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


Цитата:
Пожалуй, и закончу его работающим запросом.



Да, это было бы неплохо. Вот только добавляем в таблицу еще одну запиcь:

Код:
INSERT INTO `test_comments` (`id`, `user_id`, `comment`, `comment_date`) VALUES
(7, 2, 'Четвертый комментарий', '2008-02-19 19:29:40');


...и видим, что он нерабочий:

Код:
+------+-----------------------+
| name | comment               |
+------+-----------------------+
| Вася | Третий комментарий    |
| Петя | Третий комментарий    |
| Петя | Четвертый комментарий |
+------+-----------------------+


А так -- да, сойдет.
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Сообщение Добавлено: 20 Февраль 2008, 00:11:10 
Слушай, критик... :killanasshole:
Код:
select name, t1.comment
from test_users, test_comments t1
left join test_comments t2
on t1.user_id = t2.user_id
and t1.id < t2.id
where t2.id is null
and t1.user_id = test_users.id
order by t1.id desc


Код:
name  |  comment
Петя  |  Четвертый комментарий
Вася  |  Третий комментарий


Ты сам-то можешь хоть что-нить написать?

_________________
{'L'}('J')
Crazy Муж.
Модератор
107
Сообщения: 14561
Зарегистрирован: 23.12.01
Откуда: Moscow
Сообщение Добавлено: 20 Февраль 2008, 00:19:33 

Арт Директор писал(а):
Слушай, критик... :killanasshole:



Друг мой, искренне советую не хамить.


Цитата:
Ты сам-то можешь хоть что-нить написать?



Это мы уже обсуждали.
Арт Директор Муж.
новый человек
15
Сообщения: 128
Зарегистрирован: 07.09.05
Откуда: Москва
Сообщение Добавлено: 20 Февраль 2008, 00:46:16 

Crazy писал(а):
Ну что ж еще делать, если ты не в состоянии сам ее прочитать? :)



Чудо, а не модератор! Как я мог помыслить нахамить такому воспитанному человеку! :gent:

:bye:

_________________
{'L'}('J')
*   Список форумов / Начинка и техника / Программирование для WWW « | » » ответить » создать топик
 Страница 1 из 1 [ Сообщений: 19 ] 
Показать сообщения за:   Поле сортировки  
Найти:
Перейти:  
Уровень доступа: Вы не можете начинать темы. Вы не можете отвечать на сообщения. Вы не можете редактировать свои сообщения. Вы не можете удалять свои сообщения. Вы не можете добавлять вложения.
cron


ООО ДеФорум
При использовании материалов сайта ссылка на DeForum.ru — обязательна.
Проект Павла Батурина ©2001-2077; // Powered by phpBB © 2013 phpBB Group
Rambler's Top100