Модульні уроки (4/4)
Групи фільтрації: HAVING
Як тільки у вас є результат на групу (попередній урок), вам часто хочеться
зберігати лише групи, які задовольняють умову: відділи з більшою кількістю
більше 2 осіб, проекти із середнім бюджетом понад 100 тис., користувачі с
не менше 10 замовлень. Для цього WHERE недостатньо.
Чому WHERE недостатньо
WHERE фільтрує рядки таблиці, перед агрегацією. Тому не видно
результат COUNT(*) або AVG(...): під час виконання WHERE ті
значення ще не обчислено.
-- 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.
Синтаксис
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM table
GROUP BY grouping_column
HAVING condition_on_aggregate;-- 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 подумки їх виконує:
FROM/JOIN— будує початкову таблицю шляхом об’єднання джерел.WHERE— видаляє рядки, які вас не цікавлять.GROUP BY— збирає решту рядків у групи.HAVING— скидає групи, які вам не байдужі.SELECT— обчислює остаточні стовпці (включаючи агрегати).ORDER BY/LIMIT— змінити порядок і вирізати.
Важливі зауваження:
- у
WHEREможна використовувати лише стовпці таблиці; - у
HAVINGви можете використовувати групування стовпців і агрегатів.
-- 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;Спробуйте
Для кожного відділу вкажіть назву (departments.name) і кількість співробітників, АЛЕ лише для відділів, у яких принаймні 2 співробітники. Дві колонки, по одному рядку на кваліфікаційне відділення.
Показати підказку
Умова «принаймні 2» стає COUNT(*) >= 2 у HAVING.
Рішення доступне після 3 спроб
Повторна вправа
Покажіть відділи (departments.name), середня зарплата яких перевищує 35000. Розглянемо лише працівників, найнятих з 2018 року. Дві колонки: найменування та середнє. Сортувати за середнім за спаданням.
Показати підказку
WHERE фільтрує рядки (співробітники, найняті з 2018 року), HAVING фільтрує групи (середнє > 35000).
Рішення доступне після 3 спроб