Фильтрация групп: HAVING
WHERE и HAVING — два разных фильтра
Мы умеем фильтровать строки (WHERE) и считать итоги по группам (GROUP BY). А как отфильтровать сами группы — например, «оставить только страны, где не меньше 100 аэропортов»? Тут WHERE не подойдёт: он работает до группировки и не знает про COUNT(*). Для фильтрации групп есть отдельный раздел — HAVING:
SELECT country, COUNT(*) AS cnt
FROM airports
GROUP BY country
HAVING COUNT(*) >= 100
ORDER BY cnt DESC, country;
Разница в одной фразе:
WHERE— фильтрует строки до группировки (не может использовать агрегаты);HAVING— фильтрует группы после агрегации (в нём как раз используютCOUNT,SUMи т.п.).
Полный порядок выполнения
Теперь у нас собрался почти весь запрос. База вычисляет его в таком порядке:
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
Поэтому WHERE отсеивает строки до группировки, а HAVING — группы после. Часто их используют вместе: сначала WHERE сужает строки, потом GROUP BY группирует, потом HAVING отбрасывает мелкие/ненужные группы.
Типичные ошибки
- Псевдоним в HAVING.
HAVING cnt >= 100в PostgreSQL не сработает:HAVINGвыполняется раньшеSELECT, где появляется псевдоним. Повторите выражение:HAVING COUNT(*) >= 100. А вот вORDER BYпсевдоним уже доступен. - Обычное условие в HAVING.
HAVING country = 'Japan'сработает, но такое условие честнее и обычно эффективнее писать вWHERE: строки отсеются ещё до группировки. - HAVING без GROUP BY. Тогда вся таблица считается одной группой, и условие проверяется один раз — запрос вернёт либо одну строку, либо ничего.
💡 Практическое правило: условие по исходным строкам → вWHERE; условие по результату агрегата (COUNT(*) > 5и т.п.) → вHAVING. Неагрегированное условие иногда можно записать и вHAVING, ноWHEREяснее и обычно позволяет раньше сократить объём данных.
Практика
7- Тест 1 — Куда поставить условие «COUNT(*) >= 100»?
- Тест 2 — Почему в PostgreSQL не сработает «HAVING cnt >= 100», где cnt — псевдоним из SELECT?
- Задача 1 — Страны со 100+ аэропортами
- Задача 2 — Вместительные самолёты (200+ мест)
- Задача 3 — Страны с 50–100 аэропортами
- Задача 4 — Бронирования на несколько пассажиров
- Задача 5 — WHERE + GROUP BY + HAVING вместе
Задачи решаются прямо здесь, в браузере, на учебной базе — нужна только бесплатная регистрация, чтобы сохранялись ответы и прогресс.
Потренируйтесь в тренажёре
4Задачи на ту же тему, но на другой базе — продажи магазина электроники. Хороший способ проверить, что тема понятна, а не просто запомнилась на примерах урока.