Saltar al contenido principal
eLearner.app
Módulo 3 · Lección 4 de 412/57 en el curso~8 min
Lecciones del módulo (4/4)

Filtrare i gruppi: HAVING

Una volta che hai un risultato per gruppo (lezione precedente), spesso vuoi tenere solo i gruppi che soddisfano una condizione: i dipartimenti con più di 2 persone, i progetti con budget medio sopra 100k, gli utenti con almeno 10 ordini. Per fare questo WHERE non basta.

Perché non basta WHERE

WHERE filtra le righe della tabella, prima dell'aggregazione. Quindi non può vedere il risultato di COUNT(*) o AVG(...): nel momento in cui WHERE agisce, quei valori non sono ancora stati calcolati.

SQL
-- ERRORE: COUNT(*) non esiste ancora quando WHERE viene valutato
SELECT department_id, COUNT(*) AS count
FROM   employees
WHERE  COUNT(*) > 2     -- ❌ non funziona
GROUP BY department_id;

Per filtrare dopo l'aggregazione c'è una clausola apposita: HAVING.

La sintassi

SQL
SELECT colonna_di_raggruppamento, FUNZIONE_AGGREGATA(...)
FROM   tabella
GROUP BY colonna_di_raggruppamento
HAVING   condizione_sull_aggregato;
SQL
-- Dipartimenti con più di 2 dipendenti:
SELECT department_id, COUNT(*) AS count
FROM   employees
GROUP BY department_id
HAVING   COUNT(*) > 2;

HAVING è a GROUP BY quello che WHERE è a FROM: la stessa idea ("filtra"), ma applicata dopo il raggruppamento, sull'aggregato.

L'ordine logico delle clausole

Per non confondere mai più WHERE e HAVING, ricorda l'ordine in cui SQL le esegue mentalmente:

  1. FROM / JOIN — costruisce la tabella di partenza unendo sorgenti.
  2. WHERE — scarta le righe che non interessano.
  3. GROUP BY — raccoglie le righe rimaste in gruppi.
  4. HAVING — scarta i gruppi che non interessano.
  5. SELECT — calcola le colonne finali (compresi gli aggregati).
  6. ORDER BY / LIMIT — riordina e taglia.

Note importanti:

  • in WHERE puoi usare solo colonne della tabella;
  • in HAVING puoi usare colonne di raggruppamento e aggregati.
SQL
-- Combo classica: filtra prima, raggruppa, filtra i gruppi, ordina.
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'   -- filtra righe
GROUP BY d.name
HAVING   AVG(e.salary) > 35000      -- filtra gruppi
ORDER BY average DESC;

Prova tu

Ejercicio#sql.m3.l4.e1
Intentos: 0Cargando...

Per ogni dipartimento, mostra il nome (departments.name) e il numero di dipendenti, MA solo per i dipartimenti con almeno 2 dipendenti. Due colonne, una riga per dipartimento qualificato.

Cargando editor...
Mostrar pista

La condizione 'almeno 2' diventa COUNT(*) >= 2 in HAVING.

Solución disponible después de 3 intentos

Esercizio di ripasso

Ejercicio#sql.m3.l4.e2
Intentos: 0Cargando...

Mostra i dipartimenti (departments.name) il cui stipendio medio supera 35000. Considera solo i dipendenti assunti dal 2018 in poi. Due colonne: name e la media. Ordina per media decrescente.

Cargando editor...
Mostrar pista

WHERE filtra le righe (dipendenti assunti dal 2018), HAVING filtra i gruppi (media > 35000).

Solución disponible después de 3 intentos