Перейти к основному содержимому
Модуль 3 · Урок 4 из 412/57 в курсе~8 min
Уроки модуля (4/4)

Группы фильтрации: HAVING

Когда у вас есть результат по группе (предыдущий урок), вам часто захочется оставлять только те группы, которые удовлетворяют условию: отделы с более более 2 человек, проекты со средним бюджетом выше 100 тыс., пользователи с не менее 10 заказов. Для этого WHERE недостаточно.

Почему ГДЕ недостаточно

WHERE фильтрует строки таблицы, перед агрегированием. Поэтому он не может видеть результат COUNT(*) или AVG(...): к моменту запуска WHERE эти значения еще не рассчитаны.

SQL
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM   employees
WHERE  COUNT(*) > 2     -- ❌ doesn't work
GROUP BY department_id;

Для фильтрации после агрегирования существует специальное предложение: HAVING.

Синтаксис

SQL
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM   table
GROUP BY grouping_column
HAVING   condition_on_aggregate;
SQL
-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM   employees
GROUP BY department_id
HAVING   COUNT(*) > 2;

HAVING для GROUP BY то же самое, что WHERE для FROM: та же идея («фильтр»), но применяется после группировки в совокупности.

Логический порядок предложений

Чтобы никогда больше не путать WHERE и HAVING, запомните порядок, в котором SQL мысленно выполняет их:

  1. FROM / JOIN — строит стартовую таблицу путем объединения источников.
  2. WHERE — удаляет ненужные строки.
  3. GROUP BY — собирает оставшиеся строки в группы.
  4. HAVING — удаляет группы, которые вам не интересны.
  5. SELECT — вычисляет итоговые столбцы (включая агрегаты).
  6. ORDER BY / LIMIT — изменить порядок и вырезать.

Важные примечания:

  • в WHERE можно использовать только столбцы таблицы;
  • в HAVING вы можете использовать группировку столбцов и агрегатов.
SQL
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM   employees   AS e
JOIN   departments AS d ON e.department_id = d.id
WHERE  e.hired_on >= '2018-01-01'   -- filter rows
GROUP BY d.name
HAVING   AVG(e.salary) > 35000      -- filter groups
ORDER BY average DESC;

Попробуйте это

Упражнение#sql.m3.l4.e1
Попыток: 0Загрузка…

Для каждого отдела покажите название (departments.name) и количество сотрудников, НО только для отделов, в которых минимум 2 сотрудника. Две колонки, по одной строке на квалификационное отделение.

Загрузка редактора…
Показать подсказку

Условие «минимум 2» становится COUNT(*) >= 2 в HAVING.

Решение доступно после 3 попыток

Обзор упражнения

Упражнение#sql.m3.l4.e2
Попыток: 0Загрузка…

Укажите отделы (departments.name), средняя зарплата которых превышает 35000. Учитывайте только сотрудников, принятых на работу с 2018 года. Две колонки: имя и среднее значение. Сортировать по среднему убыванию.

Загрузка редактора…
Показать подсказку

ГДЕ фильтрует строки (сотрудники, принятые на работу с 2018 года), ИМЕЮ фильтрует группы (в среднем > 35000).

Решение доступно после 3 попыток