Сортируем а затем групируем

Возникла необходимость найти ID строк, в которых у товара максимальный приоритет вывода. Казалось бы должен помочь запрос:

SELECT * FROM goods_img GROUP BY good_id ORDER BY sort DESC

Однако, этот запрос сначала группирует, а затем сортирует, а нам нужно наоборот.

Для начала схема таблицы:

CREATE TABLE goods_img (
id int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ИД изображения',
good_id int(10) UNSIGNED NOT NULL COMMENT 'ID товара (goods.id)',
sort int(11) NOT NULL COMMENT 'Приоритетность изображения',
PRIMARY KEY (id),
UNIQUE INDEX sort_good (good_id, sort)
)
ENGINE = MYISAM COMMENT = 'Изображения товаров (у каждого товара может быть множество изображений)';

Самое простой и нелепый вариант, который дает неправильное решение, такой:

SELECT * FROM goods_img AS t1
WHERE t1.sort = ( SELECT MAX( t1.sort ) FROM goods_img WHERE id = t1.id )
GROUP BY t1.good_id

Следующий вариант найденный в просторах интернета, уверяет, что сначала можно отсортировать, а затем сгрупировать:

SELECT * FROM
   ( SELECT * FROM goods_img ORDER BY sort DESC ) as my_table_tmp
GROUP BY good_id

Говорят, что GROUP BY берет данные первой строки, поэтому такой запрос сработал правильно, но мы не будем доверять тому, что говорят и напишем правильно:

SELECT t1.id, t1.good_id, t1.sort
FROM goods_img AS t1
LEFT JOIN goods_img AS t2 ON t2.good_id = t1.good_id AND t2.sort > t1.sort
WHERE t2.sort IS NULL

Этим запросом мы нашли строки товаров, у которых t2.sort будет равен NULL, потому что подумайте логически, ведь у каждого good_id будет такая sort больше которой быть не может, вот в этих строках и возникает NULL. Данный пример для сортировки DESC, а для сортировки ASC просто поменяйте знак больше на меньше.

Заметка:

А если бы мы не делали уникальный индекс (обычно его не делают):

UNIQUE INDEX sort_good (good_id, sort)

Тогда результ может содержать повторяющиеся строки и чтобы избавиться от них (ведь они полностью идентичны согласно условиям сортировки), мы должны добавить в наш запрос:

GROUP BY t1.good_id

Более подробно про GROUP BY: 1 - 2

p.s. DISTINCT vs GROUP BY

По сути это одно и тоже, но GROUP BY дает возможность использовать HAVING:

SELECT good_id FROM goods_img GROUP BY good_id HAVING COUNT(*) > 10

а вот дополнительно отфильтровать с помощью DISTINCT не выйдет, удачки! 

Оцени публикацию:
  • 3,14
Оценили человек: 3
Теги : mysql, group by, sort, нюансы

Похожие статьи:

Справочники и учебники:


Предложения и пожелания:
Ваше имя:
Ваш E-mail:
Сколько будет Οдин + Τри
Главная
X

Новые заметки:

Про что мы забываем когда делаем оценку задачи по времени

Список вопросов для собеседования разработчика по телефону

Symfony2 авторизация без Doctrine2 для чайника

Phpstorm7 LiveEdit

Жесткий хабр или не хабр, тогда кто?

Яндекс.Деньги мошенничество

Как узнать какие страницы в поиске яндекса или это секрет

Последние комменты:

Yapro CMS:

Здравствуйте, Гость | Войти | Регистрация | Карта сайта | RSS ленты | Ошибка в тексте? Выделите её мышкой и нажмите: Ctrl + Enter

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2018 YaPro.Ru

Главная » Веб-мастеру » MySQL »