Оконные функции в SQL — стандартный инструмент аналитики. Один из частых кейсов: найти «лучшие» записи внутри каждой группы, не сворачивая таблицу и не теряя строки.
Представим таблицу:
products(id, category, price)
Нужно выбрать самый дорогой товар в каждой категории, но при этом видеть все колонки строки:
SELECT *
FROM (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC, id DESC) AS rn
FROM products
) t
WHERE rn = 1;
PARTITION BY формирует независимые окна для каждой категории.ROW_NUMBER() нумерует строки внутри каждой партиции, а не по всей таблице.Если нужны не только первые, а, например, топ-3 в каждой категории:
SELECT id, category, price
FROM (
SELECT
id, category, price,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC, id DESC) AS rn
FROM products
) t
WHERE rn <= 3
ORDER BY category, price DESC;
Тут важно: без
PARTITION BY запрос взял бы топ-3 по всей таблице, а не по категориям.Оконные функции не требуют
GROUP BY, потому что не агрегируют (не схлопывают) строки, а дополняют их аналитическими метками.Ещё полезный трюк — находить максимум в группе без
GROUP BY и JOIN, через коррелированный подзапрос:SELECT *
FROM products
WHERE price = (
SELECT MAX(price)
FROM products p2
WHERE p2.category = products.category
);
Этот запрос не агрегирует основную таблицу и вернёт несколько строк, если в категории есть товары с одинаковой максимальной ценой (
ties).🔥 Используйте
PARTITION BY в оконных функциях, когда логика должна применяться внутри каждой группы независимо, а строки нужно сохранить целиком.➡️ SQL Ready | #практика