GROUP BY и HAVING
Содержание курса
WHERE против HAVING: момент применения фильтра и совместное использование
Ключевое различие между WHERE и HAVING — это момент, в который каждый из них вступает в работу.
WHERE применяется до группировки. Строки, не прошедшие условие, исчезают из набора данных до того, как GROUP BY успел их увидеть. Агрегатная функция даже не знает об их существовании.
HAVING применяется после группировки. К этому моменту все группы уже собраны и агрегаты вычислены. HAVING просто выбрасывает группы, которые не удовлетворяют условию.
Практически это означает: попытка написать WHERE COUNT(*) > 3 завершится ошибкой — в момент выполнения WHERE никаких агрегатов ещё не существует. Агрегатные функции в WHERE запрещены синтаксически.
Вот запрос, где оба предложения работают вместе:
SELECT category, COUNT(*) AS количество
FROM products
WHERE price > 100
GROUP BY category
HAVING COUNT(*) >= 3;
Что здесь происходит: WHERE price > 100 сначала отсекает все дешёвые товары — в группировку идут только строки, прошедшие фильтр. Затем GROUP BY category собирает оставшиеся строки по категориям. Наконец, HAVING COUNT(*) >= 3 оставляет только те категории, в которых после фильтрации по цене осталось хотя бы три товара.
Это принципиально иной результат, чем если бы WHERE отсутствовал: без него в подсчёт вошли бы и дешёвые товары. Предварительный фильтр может только сохранить или уменьшить COUNT(*) каждой категории, поэтому некоторые категории перестанут проходить порог >= 3, но новые из-за фильтра не появятся.
Практическое правило выбора: если условие можно проверить на уровне отдельной строки без агрегации — используйте WHERE; если условие требует знания итогового значения по группе — используйте HAVING. Фильтрация через WHERE ещё и эффективнее: чем меньше строк дойдёт до группировки, тем меньше работы у GROUP BY.
