WHERE фильтрует строки до выполнения группировки и агрегаций, то есть определяет, какие записи попадут в группировку/агрегацию. HAVING фильтрует группы уже после применения агрегатных функций.
Пример:
-- Получить отделы с суммарной зарплатой больше 50000, исключая уволенных сотрудников SELECT department, SUM(salary) as total FROM employees WHERE status = 'active' GROUP BY department HAVING SUM(salary) > 50000;
Здесь:
Можно ли использовать агрегатные функции в WHERE?
Ошибка: пытаются написать WHERE SUM(amount) > 100, но так нельзя — агрегатные функции применяются ТОЛЬКО в HAVING.
Пример (НЕправильно):
SELECT customer_id, SUM(amount) FROM orders WHERE SUM(amount) > 100 GROUP BY customer_id -- ERROR: неверное использование SUM() в WHERE
Правильно:
SELECT customer_id, SUM(amount) FROM orders GROUP BY customer_id HAVING SUM(amount) > 100;
История
Разработка CRM. Попытка отфильтровать клиентов с количеством заказов >5 через WHERE COUNT(order_id) > 5. Запрос не работал. Итог: количество клиентов в отчёте некорректно, так как COUNT нельзя использовать в WHERE.
История
Бизнес-аналитика. Вместо фильтрации неактивных товаров в WHERE использовали HAVING. Результат: агрегирование "пустых" групп и медленный SQL. Исправлено переносом фильтра по статусу в WHERE.
История
Сложный отчет. Использовали HAVING без GROUP BY для фильтрации отдельных строк. В некоторых СУБД это вызывает ошибку, в других — неочевидное поведение. Вывод: HAVING должен идти после группировки и для агрегатных условий.