Dai, ripassiamo ancora una volta l’ordine di esecuzione delle operazioni in SQL, e anche con cosa può e non può lavorare WHERE e HAVING. È un punto importante, su cui poi si costruiscono un sacco di sfumature nel lavoro con le query SQL. Devi capirlo davvero bene.
Quindi, in cosa WHERE è diverso da HAVING, quando usare uno e quando l’altro, e come sono collegati tra loro? Questo ti aiuterà a non confonderti nella logica delle query e a filtrare i dati in modo efficace. Facciamo un riassunto delle nostre conoscenze su WHERE e HAVING.
Cos’è WHERE?
WHERE — è una condizione che si usa per filtrare le righe prima della group by o dell’uso di funzioni di aggregazione. Cioè, prima si selezionano dalla tabella le righe che rispettano i criteri, e solo dopo si fa la group by sui dati rimasti.
👉 Immagina di raccogliere frutta al mercato. WHERE è il filtro che ti aiuta a scartare in anticipo le mele rovinate, ancora prima di iniziare a dividerle per dimensione o colore.
Esempio:
SELECT *
FROM students
WHERE age > 18;
Questa query selezionerà tutti gli studenti con più di 18 anni prima di qualsiasi altra operazione.
Cos’è HAVING?
HAVING — è un filtro che si applica dopo la group by (GROUP BY). Ti permette di mettere condizioni sui dati raggruppati, tipo lasciare solo quei gruppi dove la media dei voti degli studenti è sopra 80.
👉 Torniamo alle mele. HAVING è il filtro che usi dopo aver già diviso le mele nei cesti (gruppi). Ora ti interessano, per esempio, solo i cesti (gruppi) dove ci sono più di dieci mele.
Esempio:
SELECT cesto, COUNT(*)
FROM mele
GROUP BY cesto
HAVING COUNT(*) > 10;
Questa query selezionerà solo quei cesti dove il numero di mele è maggiore di 10.
Differenze principali:
| Caratteristica | WHERE |
HAVING |
|---|---|---|
| Applicazione | Filtra le righe prima della group by | Filtra i gruppi dopo la group by |
| Uso con aggregazione | Non puoi usare funzioni di aggregazione | Puoi usare funzioni di aggregazione |
| Obiettivo | Toglie le righe inutili per la group by | Toglie i gruppi che non rispettano la condizione |
Ordine di esecuzione di WHERE, GROUP BY e HAVING
Per capire meglio come funzionano WHERE e HAVING, vediamo l’ordine di esecuzione delle query SQL:
- Prima si esegue
FROM, si selezionano le righe dalla tabella. - Poi si applica
WHERE, filtrando solo le righe che rispettano le condizioni. - Dopo si fa la group by con
GROUP BY. Otteniamo una nuova tabella con i dati raggruppati. - Si applica
HAVING, filtrando i gruppi che rispettano le condizioni. - Infine, si selezionano i risultati con
SELECT.
In modo schematico è così:
1. FROM → 2. WHERE → 3. GROUP BY → 4. HAVING → 5. SELECT
Esempio:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE age > 18
GROUP BY department
HAVING AVG(age) > 20;
Qui succede questo:
- Nella tabella
studentssi selezionano le righe doveage > 18(si usaWHERE). - Le righe rimaste vengono raggruppate per
department. - Per ogni gruppo si calcola l’età media degli studenti.
- I gruppi dove l’età media è minore o uguale a 20 vengono esclusi con
HAVING. - Si mostrano i risultati.
Esempi di uso combinato
Esempio 1: Filtraggio prima e dopo la group by
Condizione: trovare i dipartimenti dove ci sono più di 5 studenti, considerando solo gli studenti con più di 18 anni.
Tabella di partenza 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 |
Query:
SELECT department, COUNT(*) AS student_count
FROM students
WHERE age > 18
GROUP BY department
HAVING COUNT(*) > 5;
Risultato: -- Risultato della query
| department | student_count |
|---|---|
| ComputerSci | 6 |
Spiegazione:
- Prima togliamo le righe dove
age <= 18(condizioneWHERE). - Raggruppiamo i dati per dipartimento (
GROUP BY department). - Calcoliamo il numero di studenti in ogni gruppo.
- Togliamo i gruppi dove ci sono meno o uguale a 5 studenti (
HAVING COUNT(*) > 5).
Esempio 2: Errore usando WHERE invece di HAVING
Condizione: trovare i dipartimenti dove l’età media è maggiore di 22 anni.
Query sbagliata:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE AVG(age) > 22
GROUP BY department;
Errore: SQL non permette di usare funzioni di aggregazione AVG in WHERE, perché in quel momento gli aggregati non sono ancora calcolati.
Query corretta:
SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 22;
Qui la condizione AVG(age) > 22 si applica dopo la group by.
Consigli pratici
Se devi filtrare le righe, usa WHERE. Esempio: trovare tutti i dipendenti con stipendio sopra 5000.
SELECT *
FROM employees
WHERE salary > 5000;
Se devi filtrare i gruppi, usa HAVING. Esempio: trovare i reparti con stipendio totale sopra 100 000.
SELECT department, SUM(salary) AS total_salary
FROM employees
GROUP BY department
HAVING SUM(salary) > 100000;
Combina WHERE e HAVING per condizioni più complesse.
Esempio: trovare i paesi con più di 10 milioni di abitanti, considerando solo le città con popolazione sopra 1 milione.
SELECT country, SUM(population) AS total_population
FROM cities
WHERE population > 1000000
GROUP BY country
HAVING SUM(population) > 10000000;
Errori tipici e come risolverli
Uno degli errori più comuni è confondere WHERE e HAVING. Per esempio, provare a usare una funzione di aggregazione in WHERE:
SELECT department, COUNT(*)
FROM students
WHERE COUNT(*) > 10
GROUP BY department;
Questa query darà errore, perché i calcoli di aggregazione non sono disponibili nella fase WHERE. Il modo giusto è usare HAVING:
SELECT department, COUNT(*)
FROM students
GROUP BY department
HAVING COUNT(*) > 10;
Un altro errore è scegliere condizioni sbagliate per WHERE. Per esempio:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE avg_age > 20
GROUP BY department;
Qui la condizione avg_age > 20 non va bene, perché avg_age non è ancora calcolato. Soluzione: sposta questa condizione in HAVING:
SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 20;
Spero che ora tu abbia una chiara idea di come sono diversi WHERE e HAVING, come usarli correttamente e come evitare gli errori più comuni. Queste conoscenze ti serviranno per creare report complessi, filtrare dati per l’analisi e ottimizzare le query. Insomma, per la maggior parte delle query SQL reali che scriverai :)
GO TO FULL VERSION