SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 04.05.2009 13:12:06

Armalon
Участник
Зарегистрирован: 04.05.2009
Сообщений: 5

Выбрать определенную строку из группы при использовании GROUP BY

Здравствуйте, такой вопрос:

таблица, по мимо всего остального, содержит поля `rating` и `one_result_id`.
в запросе я использую конструкцию "GROUP BY `one_result_id`", т.е. собираю в группу все строки, с одинаковым `one_result_id`.
При этом я хочу каким-либо образом из этой группы выделить ту строку, в которой `rating` среди всех элементов одной группы максимален.
Да, я могу узнать этот рейтинг использовав
"SELECT MAX(*) ..."
но все остальные данные строки выбираются первые попавшие, а мне по мимо рейтинга нужно всё остальное.

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


Комментарий модератора.
В статье Выбрать последнюю строку из группы приведено 5 вариантов решения в один запрос.

Неактивен

 

#2 04.05.2009 17:21:43

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбрать определенную строку из группы при использовании GROUP BY


SELECT
  (SELECT MAX(rating) FROM tbl t2 ON t2.one_result_id = t.one_result_id) as max_rating,
  t.rating,
  t.one_result_id
FROM tbl t
ORDER BY t.one_result_id
 

Данный запрос выберет все значения rating для каждого one_result_id из таблицы tbl, а так же максимальное значение rating, соответствующее значению one_result_id.

Отредактированно Magz (04.05.2009 17:22:10)

Неактивен

 

#3 04.05.2009 19:22:20

Armalon
Участник
Зарегистрирован: 04.05.2009
Сообщений: 5

Re: Выбрать определенную строку из группы при использовании GROUP BY

Забыл сказать, требования к данному запросу по времени ОЧЕНЬ критичные. Записей около 250к, присутствует условие WHERE поиска по полю VARCHAR (Это не относится к делу, но поясняет важность скорости).

На сколько я понимаю Ваш запрос вначале выбирает все максимальные рейтинги из таблицы, где one_result_id совпадают. А затем все строки. И сортирует их по рейтингу.

Вообщем хорошо, но есть два минуса:
1) По времени выполнения из за подзапроса будет долгим
2) Он из группы с совпадающими one_result_id выбирает все, а мне хотелось бы только одну строку из группы, в которой rating максимален.

Спасибо

Неактивен

 

#4 04.05.2009 22:06:53

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выбрать определенную строку из группы при использовании GROUP BY

К сожалению, стандартный SQL такую задачу «в лоб» решать не умеет. Обычно применяют всякие
хитрости и приемы (например, как написал Magz). Если Вам очень нужен быстрый запрос, то можно
пойти на денормализацию. Возможно, в Вашем случае окажется достаточно быстрым что-то типа

SELECT one_result_id, (SELECT ... FROM tablename WHERE one_result_id=x.one_result_id ORDER BY rating DESC LIMIT 1)
FROM tablename x

Неактивен

 

#5 05.05.2009 10:48:23

Armalon
Участник
Зарегистрирован: 04.05.2009
Сообщений: 5

Re: Выбрать определенную строку из группы при использовании GROUP BY

К сожалению такой запрос выполняется сравнительно очень долго. На данный момент на практике использую такой метод:
Выбираю все подходящие под условие данные и обрабатываю их уже внутри кода. Главное – быстрый запрос.
Жаль, что SQL не позволяет выбрать определенную строку из группы. Попробую использовать денормализацию, как Вы посоветовали.

В любом случае Спасибо!

Неактивен

 

#6 05.05.2009 14:16:29

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выбрать определенную строку из группы при использовании GROUP BY

При наличии ключика на (one_result_id, rating) он должен выполняться очень-очень быстро smile

Неактивен

 

#7 05.05.2009 15:05:25

Armalon
Участник
Зарегистрирован: 04.05.2009
Сообщений: 5

Re: Выбрать определенную строку из группы при использовании GROUP BY

Сделал составной индекс (one_result_id, rating). Использую MySQL. 30к записей на локалке. Запрос получился такой:


SELECT one_result_id, (SELECT `one_result_id` FROM `search_suggestion` WHERE one_result_id=x.one_result_id ORDER BY `rating` DESC LIMIT 1)
FROM `search_suggestion` x WHERE ...
 


Время выполнения 1.7443 sec.

Как я себе представляю работает так:
Выбирает поля, соответствующие WHERE, затем для каждого делает подзапрос по всей базе и ищет совпадения one_result_id. Потом еще всё это дело сортирует дабы рейтинг максимальный был...

Т.е. к примеру, для 21 выбраной по условию строки делает еще 21 подзапрос sad

Отредактированно Armalon (05.05.2009 15:08:17)

Неактивен

 

#8 05.05.2009 15:28:33

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Выбрать определенную строку из группы при использовании GROUP BY

подозреваю, что запрос
SELECT one_result_id
FROM `search_suggestion` x WHERE ...
у Вас при этом выполняется 1.7000 sec. Правда? wink

Неактивен

 

#9 05.05.2009 17:30:14

Armalon
Участник
Зарегистрирован: 04.05.2009
Сообщений: 5

Re: Выбрать определенную строку из группы при использовании GROUP BY

Как раз нет. Всего 0.0040 sec. Что меня и настораживало...
Нашел в чем проблема:
у меня в БД из 30к записей только где-то у 4к присутствовал one_result_id!=0. для всех остальных он был нулевой. когда добавил условие "one_result_id>0" в главном запросе, то стало работать напорядок быстрее (~0.0056), что вообщем очень хорошо big_smile
Сейчас буду проводить тесты производительности и удобства данного метода. Спасибо еще раз smile

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson