Torna all'elenco degli articoli Articoli
Tempo di lettura: 6 minuti

Spiegazione della clausola HAVING in SQL

Che cos'è la clausola HAVING in SQL? Perché serve e dove si usa? Vi spieghiamo in dettaglio la clausola HAVING.

HAVING è una clausola molto comune nelle query SQL. Come WHERE, aiuta a filtrare i dati, ma HAVING funziona in modo diverso. Se conoscete la clausola GROUP BY e avete solo sentito parlare di HAVING, o se non conoscete affatto HAVING, questo articolo fa al caso vostro. Continuate a leggere e ampliate la vostra conoscenza di HAVING in SQL!

Che cos'è la clausola HAVING in SQL?

In SQL, la clausola HAVING:

  • Filtra i dati in base a criteri definiti.
  • È comunemente usata per creare rapporti.
  • Si usa solo in SELECT.
  • Funziona con GROUP BY.

Se conoscete la clausola GROUP BY, sapete che viene utilizzata per aggregare i valori: mette i record in gruppi per calcolare i valori di aggregazione (statistiche) per loro. HAVING filtra i record in base a questi valori aggregati. Ne parleremo in modo approfondito in questa sede, ma troverete maggiori dettagli nel nostro corso interattivo SQL Basics.

Se avete bisogno di un ripasso sulla clausola GROUP BY, vi consiglio gli articoli Getting the Hang of the GROUP BY Clause di Marian Dziubak e Grouping Data in SQL Server di Belma Mesihovic.

Sintassi di HAVING

Prima di iniziare con un esempio, esaminiamo la sintassi della clausola HAVING. HAVING è sempre collocata dopo le clausole WHERE e GROUP BY, ma prima della clausola ORDER BY. Guardate:

SELECT column_list 
FROM table_name
WHERE where_conditions
GROUP BY column_list
HAVING having_conditions
ORDER BY order_expression

La clausola HAVING specifica la condizione o le condizioni per un gruppo o un'aggregazione.

La tabella employee tabella sottostante ci aiuta ad analizzare la clausola HAVING. Contiene gli ID dei dipendenti (colonna emp_id ), il sito department in cui lavora il dipendente e il sito salary del dipendente.

employee_iddepartmentsalary
1HR23000
2HR28000
3Finance35000
4Marketing15000
5Marketing25000
6Finance56000
7Finance41000

Per calcolare la somma degli stipendi di ogni reparto, si scrive questa query:

SELECT department, SUM(salary)
FROM employee
GROUP BY department;

Ecco il risultato:

departmentsalary
HR51000
Marketing40000
Finance132000

Si supponga ora di dover visualizzare i reparti in cui la somma degli stipendi è pari o superiore a 50.000 dollari. In questo caso, si deve utilizzare una clausola HAVING:

SELECT department, SUM(salary)
FROM employee
GROUP BY department
HAVING SUM(salary) >= 50000;

E il risultato è:

departmentsalary
HR51000
Finance132000

Come si vede, l'insieme dei risultati contiene solo la somma degli stipendi dei reparti Risorse umane e Finanza. Questo perché la somma degli stipendi del reparto Marketing è inferiore a 50.000 dollari.

Questa query raggruppa innanzitutto i record in base ai reparti e calcola i valori aggregati, in questo caso la somma di tutti gli stipendi. Nella fase successiva, viene verificata la condizione HAVING: si confronta il valore restituito da SUM(salary) per un determinato reparto con 50.000 dollari. Se questo valore è pari o superiore a 50.000 dollari, il record viene restituito. Nel nostro esempio, vengono mostrati gli stipendi sommati dei reparti Risorse umane (51.000 dollari) e Finanza (132.000 dollari).

Filtrare le righe usando WHERE e HAVING

Vediamo poi come filtrare le righe a livello di record e a livello di gruppo nella stessa query. Per prima cosa, osservate i dati nella tabella del report sale:

salesman_idsale_monthtotal_value
1January34000
1February14000
1March22000
1April2000
2January20000
2February0
2March17000
2April0
3March1000
3April35000

La query seguente seleziona la somma di tutte le vendite per ogni venditore il cui valore medio di vendita è superiore a 20.000 dollari. (Nota: il venditore con ID=3 non è incluso, poiché ha iniziato a lavorare solo a marzo).

SELECT salesman_id, SUM(total_value)  
FROM sale 
WHERE salesman_id != 3
GROUP BY salesman_id 
HAVING SUM(total_value) > 40000;

Ecco il risultato:

salesman_idsum
172000

Questa query filtra innanzitutto i record, utilizzando la clausola WHERE per selezionare i record con ID venditore diverso da 3 (WHERE salesman_id != 3). Successivamente, calcola la somma delle vendite totali per i venditori con ID 1 e 2. A tal fine, raggruppa singolarmente i record e li seleziona. A tal fine, raggruppa singolarmente i record di entrambi i rappresentanti (GROUP BY salesman_id). Infine, la query filtra i record utilizzando HAVING per verificare se il valore aggregato (somma delle vendite totali) è superiore a 40.000 dollari (HAVING SUM(total_value) > 40000)).

Filtrare le righe su più valori con HAVING

La clausola HAVING consente anche di filtrare le righe utilizzando più di un valore aggregato (cioè valori provenienti da funzioni aggregate diverse). Osservate la prossima query:

SELECT salesman_id, SUM(total_value) 
FROM sale 
WHERE salesman_id != 3
GROUP BY salesman_id 
HAVING SUM(total_value) > 36000 AND AVG(total_value) > 15000;

Il risultato:

salesman_idsum
172000

Questa query restituisce gli ID dei venditori che 1) hanno un fatturato totale superiore a 36.000 dollari e 2) hanno una media di oltre 15.000 dollari di vendite al mese. Solo il rappresentante con ID=1 soddisfa le due condizioni. Si noti che non è stata selezionata la media delle vendite totali di ciascun venditore, ma solo la somma di tutte le vendite; la media è solo nella condizione HAVING.

La differenza tra HAVING e WHERE

L'esempio dell'ultima sezione ha mostrato come filtrare i record sia con WHERE che con HAVING. Ora considereremo la differenza tra queste due clausole.

La differenza fondamentale è che WHERE agisce sui singoli record, mentre HAVING agisce sui record raggruppati (dopo l'elaborazione di GROUP BY). HAVING si usa solo nelle istruzioni SELECT, mentre WHERE può essere usato in altre istruzioni, come DELETE o UPDATE.

HAVING e WHERE filtrano i dati in momenti diversi. WHERE viene elaborato prima di GROUP BY. Ciò significa che prima vengono selezionati i record e poi filtrati con WHERE. Si tratta di un filtraggio a livello di record. Successivamente, i record risultanti vengono raggruppati e viene calcolato il valore aggregato.

HAVING filtra i record a livello di gruppo, dopo WHERE e GROUP BY. HAVING verifica se il valore aggregato di un gruppo soddisfa le sue condizioni. È necessario utilizzare una funzione aggregata per filtrare i record solo in HAVING; WHERE non può includere una funzione aggregata.

Per saperne di più sulla differenza tra WHERE e HAVING, leggete HAVING vs WHERE in SQL: Cosa si deve saperedi Ignacio L. Bisso.

HAVING: una clausola molto utile

HAVING è molto utile nelle query SQL. Filtra i dati dopo che le righe sono state raggruppate e i valori aggregati, come spesso accade nei report.

Spero che questo articolo vi abbia aiutato a capire la clausola HAVING. Forse vi ha anche spinto ad ampliare le vostre conoscenze di SQL. Se siete interessati a saperne di più su SQL, provate il nostro corso interattivo SQL Basics corso interattivo sulla LearnSQL.it piattaforma.