Занятие 18. Фильтрация агрегированных данных. HAVING
⚡ Кратко: суть темы
HAVING фильтрует группы после агрегации, WHERE — строки до неё.
WHEREне умеет использовать агрегатные функции.HAVINGидёт послеGROUP BYи задаёт условия на агрегаты.- Порядок выполнения: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.
Частая ошибка: использовать WHERE вместо HAVING для фильтрации по COUNT/SUM.
📖 WHERE vs HAVING
Фильтрация — отбор строк или групп по условию. В SQL для этого есть два оператора, которые работают на разных этапах:
| Оператор | Когда применяется | Может использовать агрегаты | Пример условия |
|---|---|---|---|
WHERE |
До группировки, на этапе выборки строк | Нет | WHERE price > 100 |
HAVING |
После группировки и агрегации | Да | HAVING COUNT(*) > 2 |
WHERE отбрасывает строки из исходной таблицы до того, как данные будут сгруппированы. HAVING проверяет уже готовые группы и оставляет только те, которые подходят под условие.
📖 Синтаксис HAVING
Оператор HAVING размещается после GROUP BY и перед ORDER BY:
SELECT column1, aggregate_function(column2)
FROM table_name
WHERE row_condition
GROUP BY column1
HAVING group_condition
ORDER BY column1;
column1— столбец группировки.aggregate_function(column2)— агрегирующая функция, применённая к группе.group_condition— условие, по которому отбираются группы.
GROUP BY может работать без HAVING, но HAVING без GROUP BY используется редко и обычно означает фильтрацию единственной группы из всех строк.
📖 Совместное использование WHERE и HAVING
Самый эффективный подход — сначала отобрать нужные строки через WHERE, а затем отфильтровать группы через HAVING. Так СУБД обработает меньше данных на этапе группировки.
-- Сначала оставляем продукты с упаковкой 'oz', затем группируем и фильтруем
SELECT standard_cost, COUNT(product_name) AS product_count
FROM products
WHERE LOWER(quantity_per_unit) LIKE '%oz%'
GROUP BY standard_cost
HAVING COUNT(product_name) > 2
ORDER BY product_count DESC;
📖 Фактический порядок выполнения SQL-запроса
СУБД выполняет операторы не в том порядке, в котором они написаны. Понимание порядка помогает правильно выбирать между WHERE и HAVING:
FROM— выбор исходных таблиц.WHERE— фильтрация строк.GROUP BY— группировка отобранных строк.HAVING— фильтрация групп.SELECT— формирование списка столбцов.ORDER BY— сортировка результата.LIMIT— ограничение количества строк.
Проверить по документации: порядок выполнения может незначительно отличаться в разных СУБД, но общая логика FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT сохраняется в MySQL, PostgreSQL, SQLite и SQL Server.
✨ Современные практики
- Максимально сужайте набор строк через
WHEREдо группировки — это ускоряет запрос. - Не используйте агрегаты в
WHERE: пишитеHAVING COUNT(*) > 1. - В
HAVINGможно задавать несколько условий черезAND/OR. - Избегайте
SELECT *сGROUP BY— это вызывает ошибку в строгих режимах SQL.