Агрегаты, 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