Przejdź do głównej treści
eLearner.app
Moduł 3 · Lekcja 4 z 412/57 w kursie~8 min
Lekcje modułu (4/4)

Filtrowanie grup: HAVING

Kiedy już masz wynik dla każdej grupy (poprzednia lekcja), często chcesz to zrobić zachowaj tylko te grupy, które spełniają warunek: działy z większą liczbą niż 2 osoby, projekty ze średnim budżetem powyżej 100 tys., użytkownicy z co najmniej 10 zamówień. Aby to zrobić, WHERE nie wystarczy.

Dlaczego GDZIE nie wystarczy

WHERE filtruje wiersze tabeli przed agregacją. Więc nie widzi wynik COUNT(*) lub AVG(...): do czasu uruchomienia WHERE, te wartości nie zostały jeszcze obliczone.

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;

Do filtrowania po agregacji służy dedykowana klauzula: HAVING.

Składnia

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 jest dla GROUP BY tym, czym WHERE jest dla FROM: ta sama idea („filtr”), ale zastosowano po grupowaniu, łącznie.

Logiczna kolejność zdań

Aby nigdy więcej nie pomylić WHERE i HAVING, pamiętaj o kolejności SQL mentalnie je wykonuje:

  1. FROM / JOIN — buduje tabelę startową łącząc źródła.
  2. WHERE — usuwa wiersze, na których Ci nie zależy.
  3. GROUP BY — zbiera pozostałe wiersze w grupy.
  4. HAVING — usuwa grupy, na których Ci nie zależy.
  5. SELECT — oblicza końcowe kolumny (w tym agregaty).
  6. ORDER BY / LIMIT — zmień kolejność i wytnij.

Ważne uwagi:

  • w WHERE możesz używać tylko kolumn tabeli;
  • w HAVING możesz użyć kolumn grupujących i agregatów.
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;

Spróbuj

Ćwiczenie#sql.m3.l4.e1
Próby: 0Ładowanie...

Dla każdego działu podaj nazwę (departments.name) i liczbę pracowników, ALE tylko w przypadku działów zatrudniających co najmniej 2 pracowników. Dwie kolumny, jeden wiersz na każdy kwalifikujący się dział.

Ładowanie edytora...
Pokaż wskazówkę

Warunek „co najmniej 2” staje się COUNT(*) >= 2 w HAVING.

Rozwiązanie dostępne po 3 próbach

Przejrzyj ćwiczenie

Ćwiczenie#sql.m3.l4.e2
Próby: 0Ładowanie...

Pokaż działy (departments.name), których średnie wynagrodzenie przekracza 35000. Uwzględnij tylko pracowników zatrudnionych od 2018 roku. Dwie kolumny: nazwa i średnia. Sortuj według średniej malejąco.

Ładowanie edytora...
Pokaż wskazówkę

WHERE filtruje wiersze (pracownicy zatrudnieni od 2018 r.), HAVING filtruje grupy (średnia > 35000).

Rozwiązanie dostępne po 3 próbach