Все агрегатные функции работают по одному принципу: на наборе данных выполняют арифметические вычисления и возвращают итоговое значение.
Оконные агрегатные функции отличаются от обычных агрегатных функций тем, что они не изменяют количество строк в результате запроса.
Главная прелесть оконных функций, что на одни и те же данные можно смотреть в разных разрезах в рамках одного запроса.
Например, проанализируем цены на товары.
Допустим, хотим знать самую большую стоимость товара в магазине:
SELECT pp.store_id,
pp.product_id,
pp.price,
max(pp.price) over (PARTITION BY pp.store_id) as max_price_in_store
FROM product_price pp
ORDER BY pp.store_id, pp.price
# | store_id | product_id | price | max_price_in_store |
---|---|---|---|---|
1 | 201 | 6 | 17800.00 | 23500.00 |
2 | 201 | 4 | 21500.00 | 23500.00 |
3 | 201 | 3 | 22900.00 | 23500.00 |
4 | 201 | 5 | 23500.00 | 23500.00 |
5 | 300 | 1 | 10500.00 | 10500.00 |
... | ... | ... | ... | ... |
Забыл, как работает PARTITION BY
? Загляни сюда.
Посмотрели маркетологи на наш отчет и говорят: "Покажи-ка еще самый дорогой продукт по всем магазинам. А то самый дорогой продукт в магазине ни о чем не говорит..."
Ты им в ответ:
SELECT pp.store_id,
pp.product_id,
pp.price,
max(pp.price) over (PARTITION BY pp.store_id) as max_price_in_store,
max(pp.price) over () as max_price_total
FROM product_price pp
ORDER BY pp.store_id, pp.price
# | store_id | product_id | price | max_price_in_store | max_price_total |
---|---|---|---|---|---|
1 | 201 | 6 | 17800.00 | 23500.00 | 1321800000.00 |
2 | 201 | 4 | 21500.00 | 23500.00 | 1321800000.00 |
3 | 201 | 3 | 22900.00 | 23500.00 | 1321800000.00 |
4 | 201 | 5 | 23500.00 | 23500.00 | 1321800000.00 |
5 | 300 | 1 | 10500.00 | 10500.00 | 1321800000.00 |
... | ... | ... | ... | ... | ... |
"Выведи еще максимальную стоимость по этому продукту во всех магазинах..."
SELECT pp.store_id,
pp.product_id,
pp.price,
max(pp.price) over (PARTITION BY pp.product_id) as max_price_product,
max(pp.price) over (PARTITION BY pp.store_id) as max_price_in_store,
max(pp.price) over () as max_price_total
FROM product_price pp
ORDER BY pp.store_id, pp.price
# | store_id | product_id | price | max_price_product | max_price_in_store | max_price_total |
---|---|---|---|---|---|---|
1 | 201 | 6 | 17800.00 | 17900.00 | 23500.00 | 1321800000.00 |
2 | 201 | 4 | 21500.00 | 22000.00 | 23500.00 | 1321800000.00 |
3 | 201 | 3 | 22900.00 | 22900.00 | 23500.00 | 1321800000.00 |
4 | 201 | 5 | 23500.00 | 24600.00 | 23500.00 | 1321800000.00 |
5 | 300 | 1 | 10500.00 | 12500.00 | 10500.00 | 1321800000.00 |
... | ... | ... | ... | ... | ... | ... |
Агрегатных функций великое множество. Все их можно вызывать как с GROUP BY
, так и в варианте оконной функции, добавив OVER (...)
.
В большинстве задач можно обойтись джентельменским набором, разобранным в теме агрегатных функций:
avg(выражение)
- арифметическое среднее;min(выражение)
- минимальное значение выражения;max(выражение)
- маскимальное значение выражения;sum(выражение)
- сумма значений выражения;count(*)
- количество строк в результате запроса;count(выражение)
- количество значений выражения, не равныхNULL
.