Собесов

WHERE vs HAVING: когда что использовать

SQLСемантика SQLЛёгкаяJunior

Условие

В чём разница между WHERE и HAVING в SELECT-запросе?

Решение

WHERE HAVING
Когда выполняется До GROUP BY После GROUP BY
Над чем фильтрует Отдельные строки Группы (агрегатные значения)
Можно ли использовать агрегаты Нет Да
Производительность Быстрее (меньше строк в агрегации) Медленнее (агрегация всех строк)

Пример

-- неправильно: AVG в WHERE
SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 5000   -- ошибка
GROUP BY department;
 
-- правильно
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 5000;
 
-- ещё правильнее: фильтр строк до агрегации в WHERE
SELECT department, AVG(salary)
FROM employees
WHERE  hired_at >= '2020-01-01'   -- фильтрация до GROUP BY
GROUP BY department
HAVING AVG(salary) > 5000;        -- фильтрация групп после

Правило выбора

  • Условие на строку (без агрегата) → WHERE.
  • Условие на группу (с агрегатом) → HAVING.
  • Если можно положить условие в WHERE — клади. Это уменьшит объём данных для агрегации.

Ловушка с производительностью

-- плохо: агрегируем все 100M строк, потом фильтруем
SELECT user_id, COUNT(*) FROM events
GROUP BY user_id
HAVING user_id < 1000;
 
-- хорошо: фильтруем сначала
SELECT user_id, COUNT(*) FROM events
WHERE user_id < 1000
GROUP BY user_id;

Подводные камни

  1. HAVING без GROUP BY — синтаксически валиден, работает как фильтр над всем результатом (вся выборка как одна группа).
  2. Алиас в HAVING — в PostgreSQL/MySQL разрешён (HAVING cnt > 5), в Oracle — только выражение целиком.
  3. COUNT(*) vs COUNT(col) в HAVING — последний пропускает NULL, может дать сюрприз.

Эталонный ответ

WHERE фильтрует отдельные строки до агрегации, HAVING фильтрует группы после GROUP BY. Условия без агрегата всегда кладите в WHERE — быстрее.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти