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

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

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

Чому 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 року. Дві колонки: найменування та середнє. Сортувати за середнім за спаданням.

Завантаження редактора…
Показати підказку

WHERE фільтрує рядки (співробітники, найняті з 2018 року), HAVING фільтрує групи (середнє > 35000).

Рішення доступне після 3 спроб