Агрегаты, GROUP BY и HAVING

Считаем итоги по группам: агрегатные функции, GROUP BY и фильтр групп HAVING.

Агрегатная функция сворачивает множество строк в одно значение: количество, сумму, среднее, минимум или максимум.

Агрегаты по всей таблице

Без GROUP BY агрегат считается по всем строкам сразу.

CREATE TABLE sales (
  id INTEGER PRIMARY KEY,
  product TEXT,
  amount INTEGER
);

INSERT INTO sales (product, amount) VALUES
  ('Кофе', 300), ('Кофе', 250), ('Чай', 150),
  ('Чай', 200), ('Сок', 400);

SELECT COUNT(*) AS total_rows,
       SUM(amount) AS revenue,
       AVG(amount) AS avg_check
FROM sales;

Вывод:

total_rows  revenue  avg_check
5           1300      260.0

GROUP BY — итоги по группам

GROUP BY разбивает строки на группы по значению столбца, и агрегат считается отдельно для каждой группы.

CREATE TABLE sales (
  id INTEGER PRIMARY KEY,
  product TEXT,
  amount INTEGER
);

INSERT INTO sales (product, amount) VALUES
  ('Кофе', 300), ('Кофе', 250), ('Чай', 150),
  ('Чай', 200), ('Сок', 400);

SELECT product,
       COUNT(*) AS sales_count,
       SUM(amount) AS revenue
FROM sales
GROUP BY product
ORDER BY revenue DESC;

Вывод:

product  sales_count  revenue
Кофе     2            550
Сок      1            400
Чай      2            350

HAVING — фильтр по группам

Важное различие: WHERE фильтрует строки до группировки, а HAVING — готовые группы после агрегации. Условие на агрегат (например, «сумма больше 400») пишется именно в HAVING.

CREATE TABLE sales (
  id INTEGER PRIMARY KEY,
  product TEXT,
  amount INTEGER
);

INSERT INTO sales (product, amount) VALUES
  ('Кофе', 300), ('Кофе', 250), ('Чай', 150),
  ('Чай', 200), ('Сок', 400);

SELECT product, SUM(amount) AS revenue
FROM sales
GROUP BY product
HAVING SUM(amount) > 400;

Вывод:

product  revenue
Кофе     550

Группы «Сок» (400) и «Чай» (350) отсеялись — их сумма не больше 400.

WHERE и HAVING вместе

Их можно сочетать: сначала WHERE отбрасывает ненужные строки, потом данные группируются, и HAVING фильтрует группы. Порядок: WHERE → GROUP BY → HAVING.

Итог

  • Агрегаты: COUNT, SUM, AVG, MIN, MAX — сворачивают строки в одно число.
  • GROUP BY считает агрегат отдельно по каждой группе.
  • WHERE фильтрует строки до группировки, HAVING — группы после.
  • Условие на агрегат (SUM(...) > 400) ставится в HAVING, не в WHERE.
Проверьте себя
1. В чём разница между WHERE и HAVING?
Aони полностью взаимозаменяемы
BWHERE фильтрует строки до группировки, HAVING — группы после агрегации
CHAVING работает только без GROUP BY
DWHERE применяется только к числам
2. Какая функция посчитает количество строк в группе?
ASUM
BCOUNT
CAVG
DMAX
3. Где должно стоять условие SUM(amount) > 400?
Aв WHERE
Bв HAVING
Cв ORDER BY
Dв FROM
Поддержать проект