WHERE против HAVING
Чем WHERE отличается от HAVING — и почему это не взаимозаменяемые фильтры.
WHERE фильтрует отдельные строки до группировки, HAVING — целые группы после агрегации.
Суть вопроса
Оба ключевых слова фильтруют, но на разных стадиях. WHERE отсекает строки до GROUP BY — в нём нельзя использовать агрегатные функции. HAVING работает уже с готовыми группами — в нём агрегаты как раз и нужны.
Один запрос — оба фильтра
Посчитаем сумму заказов по клиентам, но: (1) учитываем только заказы дороже 100 — это про строки, значит WHERE; (2) оставляем клиентов, у которых итог больше 400 — это про группы, значит HAVING.
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer TEXT,
amount INTEGER
);
INSERT INTO orders (customer, amount) VALUES
('Аня', 500),
('Аня', 50),
('Борис', 300),
('Борис', 200),
('Вера', 90);
SELECT customer, SUM(amount) AS total
FROM orders
WHERE amount > 100 -- фильтр строк: заказ 'Аня 50' и 'Вера 90' выпадают
GROUP BY customer
HAVING SUM(amount) > 400 -- фильтр групп: остаётся только тот, у кого итог > 400
ORDER BY customer;
Вывод:
Аня|500 Борис|500
Аня: учтён только заказ 500 (заказ 50 отсёк WHERE), итог 500 — проходит HAVING. Борис: 300+200=500 — тоже проходит. Вера: единственный заказ 90 отсёк WHERE, группа исчезла ещё до HAVING.
Типичная ошибка
Поставить агрегат в WHERE — частая ошибка. Такой запрос упадёт:
SELECT customer, SUM(amount)
FROM orders
WHERE SUM(amount) > 400 -- ОШИБКА: агрегат в WHERE
GROUP BY customer;
СУБД ответит ошибкой вроде «misuse of aggregate function SUM()». Условие на сумму — это про группу, ему место в HAVING.
Памятка
| Признак | WHERE | HAVING |
| Когда работает | до группировки | после группировки |
| Над чем | над строками | над группами |
| Агрегаты | нельзя | можно и нужно |
| Без GROUP BY | обычный фильтр строк | редко, фильтр по агрегату всей таблицы |
Итог
WHERE— фильтр строк до агрегации, без агрегатных функций.HAVING— фильтр групп после агрегации, с агрегатами.- Если условие можно проверить на уровне строки — оно в
WHERE; так быстрее, ведь до группировки доходит меньше данных.