Короткий ответ
Можно использовать коррелированный подзапрос, который для каждого товара считает, сколько товаров в той же категории дороже него, и оставляет только те, где таких не больше двух (то есть товар входит в топ-3).
Как это работает подробнее
для каждой строки внешнего запроса подзапрос пересчитывает количество товаров той же категории с ценой строго больше текущей; если это количество меньше 3 (0, 1 или 2 более дорогих товара), значит текущий товар находится в первой, второй или третьей позиции по цене внутри своей категории.
Пример кода
Запрос SQL
SELECT p1.category, p1.product_name, p1.price
FROM products p1
WHERE (
SELECT COUNT(*) FROM products p2
WHERE p2.category = p1.category AND p2.price > p1.price
) < 3
ORDER BY p1.category, p1.price DESC;Что использовать на практике
- На практике: это рабочий, но не самый эффективный способ — коррелированный подзапрос выполняется для каждой строки заново, что на больших таблицах может быть медленным; на уровне Middle для этой задачи обычно используют оконную функцию
RANK()/ROW_NUMBER(), которая решает её за один проход. - Результат: Результат — до 3 (или больше при ничьих) товаров на категорию.
- Проверка: для одной категории вручную отсортировать все товары по цене и сверить с выводом.
Подводные камни
- Частая ошибка: не учитывают одинаковые цены — при использовании строгого «меньше 3 товаров дороже» два товара с одинаковой максимальной ценой оба попадут в топ-1, из-за чего итоговое количество строк на категорию может быть больше 3, и это нужно сознательно допустить или обработать отдельно.