count, sum, avg, min и max, группировка GROUP BY и условие на группы HAVING.
Агрегатные функции сворачивают много строк в одно значение:
| Функция | Что считает |
|---|---|
count(*) |
число строк |
count(колонка) |
число строк, где в колонке не NULL |
sum(колонка) |
сумму |
avg(колонка) |
среднее |
min(колонка), max(колонка) |
наименьшее и наибольшее |
SELECT count(*) AS products, min(price) AS cheapest, max(price) AS priciest
FROM products;
AS даёт колонке результата имя. В задачах нужное имя указано в условии: без AS колонка называлась бы просто
count или max.
Функции из таблицы, кроме count(*), пропускают NULL: avg делит сумму на число заполненных значений,
а не на число строк.
Строки с одинаковым значением колонки собираются в группу, и агрегат считается по каждой группе отдельно:
SELECT category_id, count(*) AS products, round(avg(price)) AS avg_price
FROM products
GROUP BY category_id;
round(x) округляет до целого, round(x, 2) — до двух знаков после запятой.
В SELECT запроса с GROUP BY можно выводить только колонки группировки и агрегаты. У группы одна строка, и
PostgreSQL не знает, какое name из десятка товаров категории показать, — запрос с name упадёт с ошибкой
must appear in the GROUP BY clause.
WHERE отбирает строки до группировки, HAVING — группы после неё. Поэтому условие на агрегат пишут в HAVING:
SELECT category_id, count(*) AS products
FROM products
WHERE price < 5000
GROUP BY category_id
HAVING count(*) >= 3;
Здесь WHERE сначала убрал товары дороже 5000 ₽, GROUP BY разложил оставшиеся по категориям, а HAVING оставил
категории, где таких товаров хотя бы три.
Сумму позиции заказа считают прямо в агрегате: sum(quantity * price) — для каждой строки умножает количество
на цену и складывает.