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 — фильтрует группы |
Можно использовать агрегаты | Нет | Да ( |
Можно использовать без 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