@aljo222
В процессе обучения веб-разработке

Как сделать правильно выборку с двойной сортировкой?

Здравствуйте!

На сайте выводятся товары с сортировкой по рейтингу (поле rating).
Также у товаров есть поле наличие (availability), в котором указывается количество остатков товара, если товара нет в наличии, то соответственно указывается 0.
Теперь понадобилось выводить все товары с сортировкой по рейтингу, но чтобы товары, которых нет в наличии (availability = 0), были в конце списка.

Так вот, сейчас запрос выглядит так:
SELECT ms2.*, ec.rating
FROM `rt_ms2_products` AS `ms2`
LEFT JOIN `rt_ms2_reviews` AS `ec` ON ms2.id=ec.id
GROUP BY ms2.id
ORDER BY ec.rating DESC
LIMIT 0, 20


Я думал, что такой запрос решит задачу, но оказалось нет. Товары с availability=0 все равно появляются в середине списка.
SELECT ms2.*, ec.rating
FROM `rt_ms2_products` AS `ms2`
LEFT JOIN `rt_ms2_reviews` AS `ec` ON ms2.id=ec.id
GROUP BY ms2.id
ORDER BY ec.rating DESC, ms2.availability DESC
LIMIT 0, 20


Соответственно вопрос: какой составить запрос, чтобы выполнить данную задачу? Использовать UNION?
  • Вопрос задан
  • 74 просмотра
Решения вопроса 1
@alexalexes
Чтобы решить задачу, нужно иметь ввиду, что order by может не только напрямую работать с колонками таблиц, но с любым вычисляемым выражением в пределах свойств одной результирующей строки.
В данном случае, вам нужно в приоритете отсортировать результат выборки по ms2.availability > 0 и ms2.availability = 0, но не беря во внимание вес значения ms2.availability.
Можно использовать выражение ms2.availability = 0, выводящее true или false, которое будет обработано order by.
SELECT ms2.*, ec.rating
FROM `rt_ms2_products` AS `ms2`
LEFT JOIN `rt_ms2_reviews` AS `ec` ON ms2.id=ec.id
GROUP BY ms2.id
ORDER BY ms2.availability = 0, ec.rating DESC
LIMIT 0, 20

Впрочем, если попадется СУБД, где нельзя работать с булевым типом в order by, то выручит case...end, результат который даст 0 или 1 - это универсальный подход.
SELECT ms2.*, ec.rating
FROM `rt_ms2_products` AS `ms2`
LEFT JOIN `rt_ms2_reviews` AS `ec` ON ms2.id=ec.id
GROUP BY ms2.id
ORDER BY case when ms2.availability = 0 then 1 else 0 end, ec.rating DESC
LIMIT 0, 20
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы