Ecco una cosa di cui non abbiamo ancora parlato: come filtrare i gruppi dopo aver applicato le funzioni di aggregazione? A volte non ci servono tutte le facoltà — solo quelle dove ci sono più di cento studenti. Oppure ci interessa vedere solo i reparti dove lo stipendio medio supera i 50.000. Oggi vediamo come filtrare i dati aggregati usando HAVING.
Perché ci serve HAVING se abbiamo già WHERE? Non si può semplicemente mettere WHERE dopo GROUP BY? :)
Non è così semplice! Prima di tutto, l'ordine degli operatori in SQL è fisso e WHERE viene eseguito prima di GROUP BY.
Magari si può spostare dopo GROUP BY?
Neanche quello! Spesso bisogna filtrare le righe della tabella prima della group by. Poi si fa la group by sui dati filtrati. E poi si buttano via i dati inutili dopo la group by.
Allora perché non prendere l'operatore WHERE, copiarlo, chiamarlo HAVING e metterlo dopo GROUP BY?
Esatto, è proprio quello che facciamo! :)
Differenza tra HAVING e WHERE
WHERE filtra le righe prima della group by.
Pensa che stai scegliendo le torte in base al gusto: fragola e cioccolato — le tieni, le altre — via. Questo è il lavoro di WHERE.
HAVING filtra dopo che i dati sono stati raggruppati e le funzioni di aggregazione hanno fatto la loro magia.
Per esempio, hai già raggruppato le torte per tavolo, hai contato quante ce ne sono e ora vuoi tenere solo i tavoli dove ci sono più di tre torte.
Quindi, HAVING si usa per filtrare i dati a livello di gruppo.
Sintassi di HAVING
La sintassi è quasi uguale a quella di WHERE, ma funziona un po' diversamente:
SELECT colonne, funzioni_aggregate
FROM tabella
GROUP BY colonne
HAVING condizione;
Fasi di esecuzione:
- Prima le righe vengono filtrate con
WHERE. - Poi i dati vengono raggruppati con
GROUP BY. - Alle righe raggruppate si applicano le funzioni di aggregazione.
- Infine, il risultato viene filtrato con
HAVING.
Esempi di utilizzo di HAVING
Esempio 1: Filtrare le facoltà con molti studenti
Vuoi sapere quali facoltà nell'università hanno più di 100 studenti. Supponiamo di avere la tabella students:
| id | name | faculty |
|---|---|---|
| 1 | Alice | Engineering |
| 2 | Bob | Engineering |
| 3 | Charlie | Arts |
| 4 | Daisy | Business |
| 5 | ... | ... |
Query:
SELECT faculty, COUNT(*) AS student_count
FROM students
GROUP BY faculty
HAVING COUNT(*) > 100;
Cosa succede qui:
- Prima raggruppiamo gli studenti per la colonna
facultyusandoGROUP BY. - Poi la funzione di aggregazione
COUNT(*)conta quanti studenti ci sono in ogni facoltà. - Infine,
HAVINGelimina tutte le facoltà dove ci sono 100 studenti o meno.
Risultato:
| faculty | student_count |
|---|---|
| Engineering | 150 |
| Arts | 120 |
Esempio 2: Reparti con stipendio medio alto
Vuoi trovare solo quei reparti dove lo stipendio medio dei dipendenti supera 50.000. Supponiamo di avere la tabella employees:
| id | name | department | salary |
|---|---|---|---|
| 1 | Alice | IT | 60000 |
| 2 | Bob | HR | 45000 |
| 3 | Charlie | IT | 70000 |
| 4 | Daisy | HR | 52000 |
| 5 | ... | ... | ... |
Query:
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;
Risultato:
| department | avg_salary |
|---|---|
| IT | 65000 |
Nota: HAVING lavora sui risultati che sono stati calcolati dopo GROUP BY.
Ordine di esecuzione di WHERE, GROUP BY e HAVING
Il filtraggio con WHERE e HAVING avviene in fasi diverse. Per capire meglio la differenza, vediamo il processo passo dopo passo di una query:
WHERE: filtraggio delle righe.Qui vengono processate tutte le righe della tabella. Se una riga non passa la condizione
WHERE, non viene nemmeno considerata dopo.GROUP BY: raggruppamento delle righe.Dopo il filtraggio, le righe vengono unite in gruppi in base alle colonne specificate in
GROUP BY.Funzioni di aggregazione:
Sui dati raggruppati si applicano funzioni come
COUNT(),AVG(),SUM()ecc.HAVING: filtraggio dei gruppi.Qui vengono processati solo i risultati delle funzioni di aggregazione. Le condizioni
HAVINGsi applicano solo ai gruppi.
Particolarità di HAVING
Particolarità 1: Lavorare con le funzioni di aggregazione
La differenza principale tra HAVING e WHERE è che HAVING lavora con le funzioni di aggregazione. Per esempio:
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;
In questa query AVG(salary) non si può usare dentro WHERE, perché WHERE lavora sulle righe prima della group by. Una query tipo:
SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;
darà errore: aggregate functions are not allowed in WHERE.
Particolarità 2: Filtraggio senza group by
Puoi usare HAVING anche senza specificare GROUP BY. In questo caso la query viene interpretata come se ci fosse un solo gruppo — tutte le righe:
SELECT AVG(salary) AS avg_salary
FROM employees
HAVING AVG(salary) > 50000;
Esempio pratico
Supponiamo di avere un negozio e la tabella delle vendite sales:
| id | product_id | sales_amount |
|---|---|---|
| 1 | 101 | 200.00 |
| 2 | 102 | 300.00 |
| 3 | 101 | 400.00 |
| 4 | 103 | 150.00 |
Query: trovare i prodotti con un totale vendite superiore a 500.
SELECT product_id, SUM(sales_amount) AS total_sales
FROM sales
GROUP BY product_id
HAVING SUM(sales_amount) > 500;
Risultato:
| product_id | total_sales |
|---|---|
| 101 | 600.00 |
Errori tipici
Uso delle funzioni di aggregazione in WHERE:
Per esempio:
SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;
Errore: non si possono usare funzioni di aggregazione in WHERE.
Errori con NULL:
Se i dati contengono NULL, il filtraggio può dare risultati strani. Per esempio:
SELECT department, SUM(salary)
FROM employees
GROUP BY department
HAVING SUM(salary) > 0;
Se la colonna salary contiene solo NULL, il risultato può essere zero o vuoto.
Complimenti! A questo punto puoi già filtrare i dati aggregati senza problemi! Ricorda che HAVING è la tua chiave per fare analisi a livello di gruppo, dove il solito WHERE non basta più.
GO TO FULL VERSION