JavaRush /Курси /SQL SELF /Фільтрація агрегованих даних з HAVING

Фільтрація агрегованих даних з HAVING

SQL SELF
Рівень 8 , Лекція 1
Відкрита

Ось про що ми ще не говорили, так це як відфільтрувати групи після застосування агрегатів? Іноді нам не потрібні всі факультети — тільки ті, де студентів більше сотні. Або нам важливо подивитись лише на відділи, де середня зарплата більша за 50,000. Сьогодні знайомимось з фільтрацією агрегованих даних через HAVING.

Навіщо нам HAVING, якщо є WHERE? Можна ж просто поставити WHERE після GROUP BY :)

Все не так просто! По-перше, порядок операторів у SQL фіксований і WHERE по цьому порядку виконується до GROUP BY.

А може можна посунути його після GROUP BY?

Теж ні! Дуже часто треба відфільтрувати рядки таблиці до групування. Потім виконати над відфільтрованими даними групування. А потім відкинути якісь непотрібні дані вже після групування.

Тоді може просто взяти оператор WHERE, скопіювати його, назвати HAVING і розмістити після GROUP BY?

Так, саме так і зробимо! :)

Відмінність HAVING від WHERE

WHERE фільтрує рядки до групування.

Уяви, що ти відбираєш торти за смаком: полуничні та шоколадні — залишаєш, а інші — в сторону. Це задача для WHERE.

HAVING фільтрує після того, як дані були згруповані і агрегатні функції зробили свою магію.

Наприклад, ти вже згрупував торти по столах, порахував їх кількість і тепер хочеш залишити лише ті столи, де тортів більше трьох.

Таким чином, HAVING використовується для фільтрації даних на рівні груп.

Синтаксис HAVING

Синтаксис майже такий самий, як у WHERE, але працює він трохи інакше:

SELECT стовпці, агрегатні_функції
FROM таблиця
GROUP BY стовпці
HAVING умова;

Етапи виконання:

  1. Спочатку рядки фільтруються через WHERE.
  2. Потім дані групуються за допомогою GROUP BY.
  3. До результатів групування застосовуються агрегатні функції.
  4. Нарешті, отриманий результат фільтрується через HAVING.

Приклади використання HAVING

Приклад 1: Фільтрація факультетів з великою кількістю студентів

Ти хочеш дізнатись, які факультети в університеті мають більше 100 студентів. Припустимо, у нас є таблиця students:

id name faculty
1 Alice Engineering
2 Bob Engineering
3 Charlie Arts
4 Daisy Business
5 ... ...

Запит:

SELECT faculty, COUNT(*) AS student_count
FROM students
GROUP BY faculty
HAVING COUNT(*) > 100;

Що тут відбувається:

  • Спочатку ми групуємо студентів по стовпцю faculty за допомогою GROUP BY.
  • Потім агрегатна функція COUNT(*) рахує кількість студентів на кожному факультеті.
  • Нарешті, HAVING відкидає всі факультети, де студентів 100 або менше.

Результат:

faculty student_count
Engineering 150
Arts 120

Приклад 2: Відділи з високою середньою зарплатою

Ти хочеш знайти лише ті відділи, де середня зарплата співробітників перевищує 50,000. Припустимо, у нас є таблиця employees:

id name department salary
1 Alice IT 60000
2 Bob HR 45000
3 Charlie IT 70000
4 Daisy HR 52000
5 ... ... ...

Запит:

SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;

Результат:

department avg_salary
IT 65000

Зверни увагу: HAVING працює з результатами, які були пораховані після GROUP BY.

Порядок виконання WHERE, GROUP BY і HAVING

Фільтрація через WHERE і HAVING відбувається на різних етапах. Щоб краще зрозуміти різницю, давай глянемо на покроковий процес запиту:

  1. WHERE: фільтрація рядків.

    На цьому етапі обробляються всі рядки таблиці. Якщо рядок не проходить умову WHERE, вона взагалі не потрапляє в подальшу обробку.

  2. GROUP BY: групування рядків.

    Після фільтрації рядки об'єднуються в групи на основі стовпців, вказаних у GROUP BY.

  3. Агрегатні функції:

    До згрупованих даних застосовуються агрегатні функції, такі як COUNT(), AVG(), SUM() і т.д.

  4. HAVING: фільтрація груп.

    На цьому етапі обробляються лише результати агрегатів. Умови HAVING застосовуються тільки до груп.

Особливості роботи HAVING

Особливість 1: Робота з агрегатами

Головна відмінність HAVING від WHERE — це робота з агрегатними функціями. Наприклад:

SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;

У цьому запиті AVG(salary) не можна використовувати всередині WHERE, бо WHERE обробляє рядки до виконання групування. Запит типу:

SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;

викличе помилку: aggregate functions are not allowed in WHERE.

Особливість 2: Фільтрація без групування

Ти можеш використовувати HAVING навіть без явного GROUP BY. У такому випадку запит буде трактуватись як такий, що має одну групу — всі записи:

SELECT AVG(salary) AS avg_salary
FROM employees
HAVING AVG(salary) > 50000;

Практичний приклад

Припустимо, у нас є магазин і таблиця продажів sales:

id product_id sales_amount
1 101 200.00
2 102 300.00
3 101 400.00
4 103 150.00

Запит: знайти товари з загальним обсягом продажів більше 500.

SELECT product_id, SUM(sales_amount) AS total_sales
FROM sales
GROUP BY product_id
HAVING SUM(sales_amount) > 500;

Результат:

product_id total_sales
101 600.00

Типові помилки

Використання агрегатів у WHERE:

Наприклад:

SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;

Помилка: агрегатні функції не можна використовувати у WHERE.

Помилки з NULL:

Якщо дані містять NULL, фільтрація може давати неочікувані результати. Наприклад:

SELECT department, SUM(salary)
FROM employees
GROUP BY department
HAVING SUM(salary) > 0;

Якщо стовпець salary містить лише NULL, результат може бути нульовим або порожнім.

Вітаю. На цьому етапі ти вже можеш впевнено фільтрувати агреговані дані! Не забувай, що HAVING — це твій ключ до аналітики на рівні груп, де звичайного WHERE вже недостатньо.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ