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

Che cos'è la clausola HAVING in SQL?

State imparando l'SQL? Vi state chiedendo per cosa si può usare la clausola clausola HAVING? O forse avete provato a utilizzare la clausola WHERE sui vostri aggregati aggregati GROUP BY? Siete nel posto giusto! In questo articolo vi spieghiamo come utilizzare HAVING con numerosi esempi.

Avete provato a filtrare le metriche create con GROUP BY con una clausola WHERE e avete scoperto che non funziona? Questo perché WHERE non fa questo. Avete bisogno di una clausola HAVING!

In questo articolo spiegheremo come utilizzare HAVING per filtrare i dati aggregati. Imparerete quando e come usarla, la sua sintassi e la differenza con WHERE. Ve lo mostreremo con esempi dettagliati tratti da una società di noleggio di film.

Siete pronti? Entriamo subito nel vivo!

Il set di dati e il problema

In questo articolo utilizziamo la tabella film dal dataset di esempio di Sakila. Essa contiene un elenco di film che è possibile noleggiare da un servizio di noleggio DVD immaginario.

Ecco un esempio di query e il suo risultato.

SELECT
	title,
	release_year,
	language_id,
	rental_duration,
	length,
	rating
FROM
	film
LIMIT 10;
titlerelease_yearlanguage_idrental_durationlengthrating
ACADEMY DINOSAUR20061686PG
ACE GOLDFINGER20061348G
ADAPTATION HOLES20061750NC-17
AFFAIR PREJUDICE200615117G
AFRICAN EGG200616130G
AGENT TRUMAN200613169PG
AIRPLANE SIERRA20061662PG-13
AIRPORT POLLOCK20061654R
ALABAMA DEVIL200613114PG-13
ALADDIN CALENDAR20061663NC-17

Con questi dati, vogliamo vedere quali tipi di film vengono noleggiati per periodi più o meno lunghi. Queste informazioni ci permetteranno di identificare il tipo di film e di pubblico su cui concentrarci.

GRUPPO PER: Un riepilogo

Utilizziamo HAVING sui gruppi creati con la clausola GROUP BY.

Facciamo un rapido promemoria di come aggregare i dati con GROUP BY. Utilizziamo GROUP BY per riassumere i dati in metriche aggregate. Abbiamo bisogno di due cose:

  • Una funzione di aggregazione come COUNT, MAX, o AVG.
  • Una colonna su cui aggregare.

Per esempio, vogliamo sapere quanti film abbiamo in ogni categoria di valutazione. Per rispondere a questa domanda, usiamo COUNT(*) per contare il numero di film in ogni gruppo e usiamo GROUP BY per aggregare questa metrica in base ai valori della colonna rating:

SELECT
	rating,
	COUNT(*) AS films
FROM
	film
GROUP BY rating
ORDER BY rating;
ratingfilms
G178
PG194
PG-13223
R195
NC-17210

Il risultato mostra il numero di film per classificazione. La distribuzione dei film per classificazione è relativamente uniforme. Il rating più diffuso è PG-13, mentre quello meno diffuso è G.

Per saperne di più su GROUP BY, consultate questo articolo di approfondimento o questo elenco di esempi pratici.

Ora che abbiamo esaminato cos'è GROUP BY, possiamo combinarlo con HAVING!

Quando usare SQL HAVING

L'uso principale dell'operazione HAVING è quello di filtrare i dati aggregati. Si può usare quando si riassumono i dati con GROUP BY in nuove metriche e si vogliono selezionare i risultati in base a questi nuovi valori.

È simile a WHERE, ma si usa in circostanze diverse. Alla fine di questo articolo, si troverà un approfondimento su questa differenza.

La sintassi di SQL HAVING

In termini di sintassi, HAVING richiede solo una riga dopo GROUP BY. Il seguente frammento riassume la sintassi necessaria per l'utilizzo di una clausola HAVING:

SELECT
	aggregate_function(column)
FROM
	table
GROUP BY column_to_aggregate_on
HAVING condition_on_aggregate_metric;

Questa sintassi è concisa, ma vediamo come funziona attraverso degli esempi!

Esempi di HAVING

Supponiamo di voler sapere quali film vengono noleggiati per un periodo più o meno lungo. Potremmo essere interessati alla durata del noleggio in base alla valutazione. Ad esempio, concentrandoci sui film con noleggi più brevi potremmo avere un turnover complessivo più veloce. Vediamo cosa ci dicono i dati su questa domanda!

Creiamo due metriche aggregate raggruppate per valutazione. Quindi, utilizziamo HAVING per filtrare la tabella risultante sulla durata media del noleggio (avg_rentdur).

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
GROUP BY rating
HAVING AVG(rental_duration) > 5

HAVING Questo filtro seleziona i dati in base a una condizione su un gruppo creato con una funzione aggregata (AVG).

ratingfilmsAVG(rental_duration)AVG(length)
PG1945.0825112.0052
NC-172105.1429113.2286
PG-132235.0538120.4439

Il risultato non include le classificazioni G e R, perché la loro durata media di noleggio è inferiore a 5 giorni. Le persone noleggiano film classificati PG, PG-13 o NC-17 per periodi più lunghi.

Interessante!

Poiché stiamo esaminando le categorie in base alla loro durata di noleggio, filtriamo ulteriormente i risultati. Rimuoveremo anche i film la cui durata media è superiore alle due ore. Per farlo, aggiungiamo un'altra condizione di gruppo alla clausola HAVING:

SELECT
	rating,
COUNT(*) AS films,
AVG(rental_duration),
AVG(length)
FROM
	film
GROUP BY rating
HAVING AVG(rental_duration) > 5
	AND AVG(length) < 120;

La condizione aggiuntiva su AVG(length) filtra la classificazione PG-13.

ratingfilmsAVG(rental_duration)AVG(length)
PG1945.0825112.0052
NC-172105.1429113.2286

Ben fatto!

Non si può usare WHERE per filtrare i gruppi

Abbiamo detto che HAVING è simile a WHERE, ma li usiamo in scenari diversi. Vediamo come funziona nel nostro esempio.

Sostituiamo HAVING con WHERE nella query appena scritta:

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
GROUP BY rating
WHERE AVG(rental_duration) > 5

Tuttavia, il risultato è il seguente messaggio di errore:

ERRORE 1064 (42000): Si è verificato un errore nella sintassi SQL; controllare il manuale corrispondente alla versione del server MySQL per conoscere la sintassi corretta da utilizzare vicino a 'WHERE avg_rentdur > 5' alla riga 9.

Questo perché le clausole GROUP BY vengono eseguite dopo le clausole WHERE. Questa query cerca di applicare WHERE a avg_rentdur quando avg_rentdur non esiste ancora!

Questo significa che possiamo usare WHERE solo su dati "grezzi" e non su valori aggregati. Dobbiamo usare HAVING per le metriche aggregate.

Utilizzo di WHERE e HAVING in una query

Abbiamo visto che si usa WHERE per filtrare le singole righe e HAVING per filtrare i gruppi. Per dimostrare ulteriormente la loro differenza, vediamo un esempio in cui utilizziamo sia HAVING che WHERE!

Vogliamo sapere come cambiano i risultati precedenti quando ci concentriamo sui film brevi. A tale scopo, limitiamo la durata dei film a 60 minuti.

Nella nostra query, lo facciamo applicando WHERE alla colonna lunghezza:

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
WHERE
	length < 60
GROUP BY rating
HAVING AVG(rental_duration) < 5;
ratingfilmsAVG(rental_duration)AVG(length)
G214.381053.0952
NC-17214.904851.3810
R114.636455.0000

I risultati mostrano che se ci concentriamo solo sui film brevi, troviamo diversi film classificati NC-17 con noleggi brevi in media. Questo risultato può darci idee sul tipo di film che possiamo introdurre nella nostra futura selezione di offerte.

Volete saperne di più sulle differenze tra HAVING e WHERE? Consultate il nostro articolo dettagliato sull'argomento!

Per saperne di più su SQL HAVING!

Vi piace quello che avete appena imparato? Assicuratevi di non dimenticarlo! Il modo migliore per imparare l'SQL è risolvere i problemi attraverso esempi nuovi e stimolanti. Potete impostare lo stesso ambiente di test che usiamo qui, importare lo stesso set di dati e riscrivere le query che avete appena imparato.

Tuttavia, questo potrebbe richiedere molto lavoro, e non fareste altro che ricreare gli stessi esempi. Vi consigliamo invece di dare un'occhiata al nostro corso di pratica! Vi aiuterà a fare pratica con l'SQL HAVING e altre clausole attraverso esempi nuovi e stimolanti!

Cosa ne pensate? Siete pronti?