Агрегаты и группировка

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 делит сумму на число заполненных значений, а не на число строк.

Группировка — GROUP BY

Строки с одинаковым значением колонки собираются в группу, и агрегат считается по каждой группе отдельно:

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.

Условие на группу — HAVING

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) — для каждой строки умножает количество на цену и складывает.

Задачи

  1. Задача 9. Сколько у нас клиентов
  2. Задача 10. Кому можно написать
  3. Задача 11. Сумма каждого заказа
  4. Задача 12. Клиенты по городам
  5. Задача 13. Средняя цена в категории
  6. Задача 14. Крупные заказы
  7. Задача 15. Хиты продаж