Короткий ответ
WHERE фильтрует отдельные строки до группировки, а HAVING фильтрует уже готовые группы после агрегации — то есть HAVING может ссылаться на результат агрегатной функции, а WHERE нет.
Как это работает подробнее
Порядок логического выполнения запроса: FROM/JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. WHERE отбрасывает строки до группировки, снижая объём данных для агрегации; HAVING применяется уже к результатам COUNT/SUM/AVG по каждой группе.
Пример кода
example.sql
SELECT customer_id, COUNT(*) AS orders_count
FROM orders
WHERE status = 'completed'
GROUP BY customer_id
HAVING COUNT(*) > 3;
-- Отбирает только завершённые заказы (WHERE), затем только клиентов с более чем 3 такими заказами (HAVING)Что использовать на практике
- Практика. Если условие можно сформулировать на уровне отдельной строки (например, status = 'active'), его стоит вынести в WHERE — это эффективнее. HAVING используют только для условий на агрегат, например HAVING COUNT(*) > 5.
Подводные камни
- Ошибка. Пытаются написать WHERE COUNT(*) > 5 — это синтаксическая ошибка, так как на момент WHERE агрегат ещё не вычислен; либо необоснованно переносят в HAVING условия, которые можно и нужно проверить в WHERE.