Нужно получить топ-3 продукта по выручке внутри каждой категории. Какой подход корректен в PostgreSQL?

AGROUP BY category ORDER BY revenue DESC LIMIT 3: ограничение по числу строк применится к каждой категории отдельно
BHAVING RANK() <= 3 поверх обычной агрегации с GROUP BY category и сортировкой выручки по убыванию
CDISTINCT ON (category) с ORDER BY category, revenue DESC LIMIT 3 для выбора трёх лучших товаров категории
DROW_NUMBER() OVER (PARTITION BY category ORDER BY revenue DESC) в подзапросе с фильтром по номеру <= 3
Правильный ответ. Паттерн «топ-N внутри группы» требует оконной функции ROW_NUMBER() OVER (PARTITION BY ...) с последующей фильтрацией по номеру строки во внешнем запросе.

Разбор

LIMIT без оконной функции ограничивает весь результат запроса, а не каждую группу отдельно. DISTINCT ON (category) даёт только топ-1. HAVING не знает о позиции строки внутри группы. Правильный подход: в CTE или подзапросе присвоить ROW_NUMBER() OVER (PARTITION BY category ORDER BY revenue DESC) AS rn, затем во внешнем запросе написать WHERE rn <= 3. При ничьих можно использовать RANK() вместо ROW_NUMBER().

Проверь себя · 1/3разбор после ответа
Есть таблица payments(amount), в части строк amount равно NULL. Какой запрос посчитает количество всех строк в таблице, включая строки с NULL в столбце amount?
Тренировать SQL в Telegram

Ещё вопросы по теме «Агрегация, GROUP BY и HAVING»