SQL HAVING

HAVING в SQL: фильтрация групп после GROUP BY — когда WHERE не подходит и как правильно использовать оба условия вместе.

HAVING — это фильтр для групп. Он делает то, что WHERE делает для строк, но применяется уже после того, как GROUP BY сформировал группы и агрегаты посчитаны.

Синтаксис

SELECT столбец, АГРЕГАТ(...)
FROM таблица
[WHERE условие_по_строкам]
GROUP BY столбец
HAVING условие_по_группам
[ORDER BY ...];

Пример 1: отделы без сотрудников

Найдём отделы, в которых нет ни одного сотрудника:

SELECT d.dept_name, COUNT(e.emp_id) AS total_employees
FROM departments d
LEFT JOIN employees e ON d.dept_id = e.dept_id
GROUP BY d.dept_name
HAVING total_employees = 0;

Результат:

+------------------+-----------------+
| dept_name        | total_employees |
+------------------+-----------------+
| Customer Service |               0 |
+------------------+-----------------+

Пример 2: отделы с суммарной зарплатой выше порога

SELECT dept_id, SUM(salary) AS total_salary
FROM employees
WHERE dept_id IS NOT NULL   -- WHERE фильтрует строки ДО группировки
GROUP BY dept_id
HAVING total_salary > 6000  -- HAVING фильтрует группы ПОСЛЕ
ORDER BY total_salary DESC;

Результат:

+---------+--------------+
| dept_id | total_salary |
+---------+--------------+
|       5 |         8000 |
|       3 |         7200 |
|       1 |         6500 |
+---------+--------------+

Пример 3: HAVING с COUNT — города с более чем одним клиентом

SELECT city, COUNT(*) AS cnt
FROM customers
GROUP BY city
HAVING cnt > 1;

Результат:

+--------+-----+
| city   | cnt |
+--------+-----+
| Madrid |   2 |
+--------+-----+

WHERE vs HAVING — в чём разница

Критерий

WHERE

HAVING

Когда применяется

До GROUP BY — фильтрует строки

После GROUP BY — фильтрует группы

Можно использовать агрегаты

Нет

Да (HAVING COUNT(*) > 2)

Можно использовать без GROUP BY

Да

Технически да, но смысла мало

Правило. Если условие можно написать в WHERE — пишите в WHERE: это быстрее, потому что строки отсеиваются до группировки. HAVING — только для условий с агрегатными функциями или на уровне группы.

Частые ошибки

  • Написать WHERE COUNT(*) > 1 — агрегаты в WHERE запрещены, только в HAVING.
  • Поставить HAVING перед GROUP BY — строгий порядок предложений нарушать нельзя.

Коротко

  • HAVING фильтрует группы после GROUP BY; WHERE фильтрует строки до группировки.
  • Только в HAVING можно использовать агрегатные функции в условии.
  • Порядок: FROM → WHERE → GROUP BY → HAVING → ORDER BY.
  • Используйте WHERE, если можно: это эффективнее, чем фильтровать уже сгруппированные данные.
Проверьте себя
1. Чем HAVING отличается от WHERE?
AHAVING применяется к отдельным строкам, WHERE — к группам
BHAVING и WHERE — синонимы, можно использовать любой
CHAVING работает только с числовыми столбцами
DWHERE применяется к отдельным строкам до группировки, HAVING — к группам после GROUP BY
2. Как найти отделы, в которых нет ни одного сотрудника, используя GROUP BY и HAVING?
AWHERE COUNT(emp_id) = 0
BWHERE emp_id IS NULL
CHAVING emp_id = 0
DHAVING COUNT(emp_id) = 0
3. Какой правильный порядок предложений: WHERE, GROUP BY, HAVING?
AHAVING → WHERE → GROUP BY
BWHERE → GROUP BY → HAVING
CGROUP BY → WHERE → HAVING
DWHERE → HAVING → GROUP BY
4. Запрос: SELECT dept_name, COUNT(emp_id) AS total FROM departments LEFT JOIN employees ... GROUP BY dept_name HAVING total = 0. Что вернёт этот запрос?
AВсе отделы
BТолько отделы с более чем одним сотрудником
CТолько отдел(ы) без сотрудников
DНичего — HAVING не может использовать псевдоним total