JavaRush /Курси /SQL SELF /Порівняння WHERE та HAVING: розбір порядку виконання і пр...

Порівняння WHERE та HAVING: розбір порядку виконання і приклади

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

Давай ще раз пройдемося по порядку виконання операцій в SQL, а також про те, з чим може і не може працювати WHERE та HAVING. Це реально важливий момент, на ньому далі будується купа нюансів роботи SQL-запитів. Тобі треба дуже добре це зрозуміти.

Так чим же WHERE відрізняється від HAVING, коли юзати один, а коли інший, і як вони пов’язані? Це допоможе не заплутатись в логіці запитів і ефективно фільтрувати дані. Давай підсумуємо наші знання про WHERE і HAVING.

Що таке WHERE?

WHERE — це умова, яка використовується для фільтрації рядків до групування або застосування агрегатних функцій. Тобто, спочатку з таблиці відбираються рядки, що підходять під критерії, а вже потім на залишених даних виконується групування.

👉 Уяви, що ти збираєш фрукти на базарі. WHERE — це фільтр, який допомагає тобі заздалегідь відсіяти некондиційні яблука, ще до того, як ти почнеш сортувати їх за розміром чи кольором.

Приклад:

SELECT *
FROM students
WHERE age > 18;

Цей запит вибере всіх студентів старше 18 років до виконання будь-яких інших операцій.

Що таке HAVING?

HAVING — це фільтр, який застосовується після групування даних (GROUP BY). Він дозволяє накладати умови на згруповані дані, наприклад, залишити тільки ті групи, де середній бал студентів більше 80.

👉 Знову до прикладу з яблуками. HAVING — це фільтр, який юзається вже після сортування яблук по кошиках (групах). Тепер тебе цікавлять, наприклад, тільки ті кошики (групи), де більше десяти яблук.

Приклад:

SELECT кошик, COUNT(*)
FROM яблука
GROUP BY кошик
HAVING COUNT(*) > 10;

Цей запит вибере тільки ті кошики, де кількість яблук більше 10.

Основні відмінності:

Особливість WHERE HAVING
Застосування Фільтрує рядки до групування Фільтрує групи після групування
Робота з агрегацією Не можна використовувати агрегатні функції Можна використовувати агрегатні функції
Мета Видаляє зайві рядки для групування Видаляє групи, які не підходять під умову

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

Щоб краще зрозуміти, як працюють WHERE і HAVING, давай подивимось на порядок виконання SQL-запитів:

  1. Спочатку виконується FROM, вибираються рядки з таблиці.
  2. Далі застосовується WHERE, фільтруються тільки ті рядки, які підходять під умови.
  3. Після цього виконується групування через GROUP BY. Ми отримуємо нову таблицю з даними груп.
  4. Застосовується HAVING, фільтруються групи, які підходять під умови.
  5. В кінці вибираються результати SELECT.

Схематично це виглядає так:

1. FROM → 2. WHERE → 3. GROUP BY → 4. HAVING → 5. SELECT

Приклад:

SELECT department, AVG(age) AS avg_age
FROM students
WHERE age > 18
GROUP BY department
HAVING AVG(age) > 20;

Тут відбувається наступне:

  1. В таблиці students вибираються рядки, де age > 18 (юзається WHERE).
  2. Залишені рядки групуються по department.
  3. Для кожної групи рахується середній вік студентів.
  4. Групи, де середній вік менше або дорівнює 20, відкидаються HAVING.
  5. Результати виводяться.

Приклади комбінованого використання

Приклад 1: Фільтрація до і після групування

Умова: знайти факультети, де більше 5 студентів, при цьому враховуються тільки студенти старше 18 років.

Початкова таблиця students

id name department age gpa
1 Alex Lin ComputerSci 20 3.8
2 Maria Chi Math 22 3.5
3 Anna Song ComputerSci 19 4.0
4 Otto Art Math 17 3.9
5 Liam Park Physics 21 3.7
6 Jane Doe ComputerSci 23 3.6
7 Tom Brown Math 25 3.4
8 Sara White Math 19 3.8
9 John Smith ComputerSci 20 3.7
10 Emily Green Physics 18 3.9
11 Mark Blue ComputerSci 21 3.5
12 Zoe Black Math 22 3.6
13 Max Gray ComputerSci 20 3.9
14 Eva Gold Math 23 3.7
15 Nick Silver Physics 19 3.8

Запит:

SELECT department, COUNT(*) AS student_count
FROM students
WHERE age > 18
GROUP BY department
HAVING COUNT(*) > 5;

Результат: -- Результат запиту

department student_count
ComputerSci 6

Пояснення:

  1. Спочатку видаляємо рядки, де age <= 18 (умова WHERE).
  2. Групуємо дані по факультетах (GROUP BY department).
  3. Рахуємо кількість студентів у кожній групі.
  4. Видаляємо групи, де студентів менше або дорівнює 5 (HAVING COUNT(*) > 5).

Приклад 2: Помилка при використанні WHERE замість HAVING

Умова: Знайти факультети, де середній вік більше 22 років.

Некоректний запит:

SELECT department, AVG(age) AS avg_age
FROM students
WHERE AVG(age) > 22
GROUP BY department;

Помилка: SQL не дозволяє використовувати агрегатні функції AVG в WHERE, бо на цьому етапі агрегати ще не пораховані.

Правильний запит:

SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 22;

Тут умова AVG(age) > 22 застосовується вже після групування.

Практичні поради

Якщо треба фільтрувати рядки, юзай WHERE. Приклад: Знайти всіх співробітників із зарплатою більше 5000.

SELECT *
FROM employees
WHERE salary > 5000;

Якщо треба фільтрувати групи, юзай HAVING. Приклад: Знайти відділи із загальною зарплатою більше 100 000.

SELECT department, SUM(salary) AS total_salary
FROM employees
GROUP BY department
HAVING SUM(salary) > 100000;

Комбінуй WHERE і HAVING для складних умов.

Приклад: Знайти країни з кількістю жителів більше 10 мільйонів, враховуючи тільки міста, де населення більше 1 мільйона.

SELECT country, SUM(population) AS total_population
FROM cities
WHERE population > 1000000
GROUP BY country
HAVING SUM(population) > 10000000;

Типові помилки і як їх уникнути

Одна з найпоширеніших помилок — це плутанина між WHERE і HAVING. Наприклад, спроба використати агрегатну функцію в WHERE:

SELECT department, COUNT(*)
FROM students
WHERE COUNT(*) > 10
GROUP BY department;

Такий запит видасть помилку, бо агрегатні розрахунки недоступні на етапі виконання WHERE. Правильний підхід — юзати HAVING:

SELECT department, COUNT(*)
FROM students
GROUP BY department
HAVING COUNT(*) > 10;

Ще одна помилка — вибір неправильних умов для WHERE. Наприклад:

SELECT department, AVG(age) AS avg_age
FROM students
WHERE avg_age > 20
GROUP BY department;

Тут умова avg_age > 20 некоректна, бо avg_age ще не порахований. Рішення — перенести цю умову в HAVING:

SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 20;

Сподіваюсь, тепер у тебе є чітке розуміння, чим відрізняються WHERE і HAVING, як їх правильно юзати і як уникати типових помилок. Ці знання реально стануть у пригоді при створенні складних звітів, фільтрації даних для аналізу і оптимізації запитів. Тобто для більшої половини реальних SQL-запитів, які ти будеш писати :)

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