GROUP BY и агрегатные функции
GROUP BY — один из самых используемых операторов в аналитических запросах. Позволяет считать метрики по группам: выручка по месяцам, число заказов по пользователям, средний чек по категориям.
Содержание
Как работает GROUP BY
GROUP BY разбивает строки таблицы на группы по одной или нескольким колонкам. К каждой группе применяется агрегатная функция.
Правило: в SELECT можно использовать только те колонки, которые указаны в GROUP BY, или агрегатные функции.
-- Выручка по каждому пользователю
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id;Агрегатные функции
COUNT(*) — количество строк в группе. COUNT(col) — количество строк, где col не NULL. SUM(col) — сумма значений. AVG(col) — среднее значение. MAX(col) / MIN(col) — максимум и минимум.
SELECT
category,
COUNT(*) AS products_count,
AVG(price) AS avg_price,
MAX(price) AS max_price,
SUM(sales_count) AS total_sales
FROM products
GROUP BY category
ORDER BY total_sales DESC;HAVING — фильтрация групп
WHERE фильтрует строки до группировки. HAVING фильтрует уже готовые группы.
Правило: если условие использует агрегатную функцию (SUM, COUNT, AVG) — используй HAVING. Если нет — WHERE.
-- Пользователи с суммой заказов > 10 000
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id
HAVING SUM(amount) > 10000;
-- Ошибка: нельзя использовать алиас в HAVING в большинстве СУБД
-- HAVING total > 10000; -- не работает в PostgreSQLGROUP BY по нескольким колонкам
Можно группировать по нескольким колонкам. Тогда группа = уникальная комбинация значений.
-- Выручка по пользователю и категории товара
SELECT
o.user_id,
p.category,
SUM(o.amount) AS revenue
FROM orders o
JOIN products p ON o.product_id = p.id
GROUP BY o.user_id, p.category
ORDER BY revenue DESC;GROUP BY с датами
Частая задача в аналитике — метрики по периодам. Используй DATE_TRUNC или EXTRACT для группировки по месяцу, неделе, году.
-- Выручка по месяцам
SELECT
DATE_TRUNC('month', created_at) AS month,
SUM(amount) AS revenue,
COUNT(*) AS orders_count
FROM orders
GROUP BY DATE_TRUNC('month', created_at)
ORDER BY month;Типичные ошибки
1. Не включил колонку в GROUP BY: SELECT user_id, name, COUNT(*) ... GROUP BY user_id — ошибка, name не в GROUP BY. 2. Перепутал WHERE и HAVING: WHERE SUM(amount) > 1000 — синтаксическая ошибка. 3. COUNT(*) vs COUNT(col): COUNT(*) считает все строки включая NULL, COUNT(col) — только не-NULL.
Закрепи знания на практике
Решай реальные задачи с собеседований прямо в браузере — без установки.
Решить задачи на GROUP BY →