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

Introduzione alla clausola HAVING di SQL: Tutorial per principianti

Siete alle prime armi con SQL e vi siete appena imbattuti nella clausola AVVIAMENTO . Ma a cosa serve? Perché è essenziale? In questo articolo approfondiremo le basi della clausola AVVIAMENTO in SQL. Inoltre, faremo degli esercizi pratici per migliorare la comprensione delle sue funzionalità.

Iniziamo definendo il linguaggio SQL (Structured Query Language). SQL è un linguaggio di programmazione potente e standardizzato, progettato specificamente per la gestione e la manipolazione dei database relazionali; in parole povere, è il modo in cui comunichiamo con i database che contengono tutti i nostri dati importanti. Con questi sistemi di database possiamo eseguire una serie di operazioni, tra cui l'interrogazione, l'aggiornamento e la gestione dei dati.

L'SQL è essenziale per una gestione e un'analisi efficaci dei dati. Ci permette di recuperare informazioni specifiche, di manipolare i dati nei database e di creare strutture di database. L'SQL offre un potente insieme di strumenti per estrarre informazioni rilevanti e generare report per l'analisi dei dati. Per saperne di più su questi database, consultate il nostro articolo Cos'è un database SQL?

L'SQL ha parole chiave e clausole (comandi) specifiche che ci aiutano a eseguire queste azioni, proprio come la grammatica e i costrutti di una lingua scritta. Un esempio è la clausola HAVING. In SQL, la clausola HAVING è utile per affinare i risultati delle query filtrando i gruppi di dati in base a condizioni specifiche. In questo articolo, per iniziare, vi illustreremo alcuni esercizi per principianti con la clausola HAVING; per una spiegazione più approfondita, consultate il nostro articolo La clausola HAVING di SQL spiegata.

Se state pensando di iniziare il vostro percorso in SQL ma non sapete da dove cominciare, il nostro SQL per principianti è un ottimo punto di partenza. In questo corso imparerete i fondamenti dell'SQL recuperando dati dai database e creando semplici report utilizzando esempi interattivi e reali. Detto questo, diamo un'occhiata più approfondita alla clausola SQL HAVING.

La clausola HAVING

La clausola HAVING lavora in tandem con la clausola GROUP BY per restringere i risultati in base alle funzioni aggregate. Le funzioni aggregate sono strumenti SQL che consentono di calcolare valori come il totale (SUM), la media (AVG) e il valore più basso (MIN) da gruppi di righe nei nostri dati.

Spieghiamo queste clausole con un esempio. Immaginiamo di avere una tabella sales che contiene i rapporti sulle vendite della nostra azienda. Possiamo usare la seguente query per trovare le regioni con vendite totali superiori a 10.000 dollari:

SELECT Region, SUM(TotalSales) as TotalSales
FROM Sales
GROUP BY Region
HAVING SUM(TotalSales) > 10000;

Ecco la ripartizione:

  • SELECT Region, SUM(TotalSales) as TotalSales: La clausola SELECT visualizza sia la colonna regione sia la somma totale delle vendite.
  • FROM Sales: La clausola FROM specifica la tabella di origine, qui, sales.
  • GROUP BY Region: La clausola GROUP BY raggruppa i dati in base alla colonna Regione. Ad esempio, se nella colonna Region sono presenti i valori "Francia", "Italia" e "Spagna", si avranno tre gruppi.
  • HAVING SUM(TotalSales) > 10000: La clausola HAVING specifica che i dati aggregati per quel valore della colonna (ad esempio, tutte le vendite di "Italia") devono avere vendite totali superiori a $10,000 per essere inclusi nel nostro set di risultati. Se le vendite totali di una regione fossero inferiori a questo valore, non comparirebbero nei risultati della nostra query.

Con HAVING, è possibile affinare i risultati delle query filtrando i dati aggregati (raggruppati) in base alle condizioni specificate. Questo permette agli utenti di concentrarsi su sottoinsiemi di dati che soddisfano criteri specifici, consentendo di estrarre informazioni significative dai set di dati.

Forse avete sentito dire che in SQL si usa la clausola WHERE per filtrare i dati. Qual è la differenza tra queste due clausole? Quale si dovrebbe usare?

In SQL, entrambe le clausole HAVING e WHERE sono importanti per filtrare i dati, ma vengono utilizzate in fasi diverse della query. Per un approfondimento, si veda il nostro articolo Qual è la differenza tra le clausole WHERE e HAVING in SQL? Per ora, vediamo alcuni esempi.

Modifichiamo leggermente la query precedente. Questa volta stiamo calcolando le vendite totali per ogni regione nel 2023:

SELECT Region,SUM(TotalSales) as TotalSales
FROM Sales
WHERE YEAR(SaleDate) = 2023
GROUP BY Region;
In this version, the WHERE clause filters individual rows before they are grouped to include only those with a sale date in 2023. Now, let’s include both the WHERE and HAVING clauses:
SELECT Region, SUM(TotalSales) as TotalSales
FROM Sales
WHERE YEAR(SaleDate) = 2023
GROUP BY Region
HAVING SUM(TotalSales) > 10000;

Qui la clausola WHERE filtra le singole righe in base alla data di vendita. Dopo l'applicazione di GROUP BY, la clausola HAVING assicura che solo le regioni con vendite totali superiori a 10.000 dollari nel 2023 siano incluse nel risultato finale.

Per riassumere:

  • WHERE si usa per filtrare le singole righe, restringendo i dati prima dell'aggregazione.
  • HAVING è usato per filtrare gruppi di righe; viene applicato ai gruppi creati dall'aggregazione.

Esempi di query con HAVING

Il modo migliore per imparare un linguaggio è la pratica, quindi in questa sezione vedremo alcuni esempi pratici per spiegare la clausola HAVING nel suo contesto. Se siete completamente inesperti di query SQL, date un'occhiata al nostro SQL per principianti Cheat Sheet per aiutarvi a navigare nelle query seguenti.

Esercizio 1: Clienti con più di un acquisto

Esercizio: Disponete dei dati di acquisto di un negozio online e il team di analisi del negozio vuole identificare i clienti che hanno effettuato più acquisti, ossia trovare i clienti che ritornano. Visualizzate gli ID dei clienti e il numero di acquisti che hanno effettuato.

Soluzione:

SELECT customer_id, COUNT(purchase_id) as purchase_count
FROM purchases
GROUP BY customer_id
HAVING COUNT(purchase_id) > 1;

Soluzione Spiegazione:

  • SELECT customer_id, COUNT(purchase_id) as purchase_count: La clausola SELECT visualizza gli ID dei clienti e il numero di acquisti effettuati.
  • FROM purchases: Specifica la tabella di origine come purchases.
  • GROUP BY customer_id: Raggruppa i dati di acquisto in base agli ID cliente, creando un gruppo per ogni cliente.
  • HAVING COUNT(purchase_id) > 1: La clausola HAVING filtra l'insieme dei risultati, includendo solo i clienti che hanno effettuato più di un acquisto.

Risultato:

customer_idpurchase_count
1035
1092
1113

Questa query evidenzia i clienti che hanno effettuato più di un acquisto, ovvero i clienti di ritorno. La clausola HAVING è fondamentale perché filtra i clienti che hanno effettuato un solo acquisto. Senza HAVING, la query restituirebbe tutti i clienti.

Esercizio 2: Riconoscere i clienti fedeli

Esercizio: Il direttore di un negozio di abbigliamento online desidera premiare i clienti che hanno effettuato almeno dieci acquisti nel 2023. Vi è stato chiesto di visualizzare l'ID cliente e il numero di ordini per i clienti che hanno effettuato più di 10 ordini lo scorso anno. Inoltre, assicuratevi che il cliente con il maggior numero di ordini appaia in cima ai risultati.

Soluzione:

SELECT customer_id, COUNT(order_id) as order_count
FROM orders
WHERE YEAR(order_date) = 2023
GROUP BY customer_id
HAVING COUNT(order_id) > 10
ORDER BY OrderCount DESC;

Soluzione Spiegazione:

  • SELECT customer_id, COUNT(order_id) as OrderCount: La clausola SELECT visualizza l'ID del cliente e il suo numero di ordini.
  • FROM orders: Specifica la tabella di origine come orders.
  • WHERE YEAR(order_date) = 2023: Filtra le righe per includere solo gli ordini a partire dal 2023.
  • GROUP BY customer_id: Raggruppa i dati in base all'ID cliente, creando un gruppo per ogni cliente.
  • HAVING COUNT(order_id) > 10: Questa clausola limita il set di risultati ai clienti con più di dieci ordini.
  • ORDER BY OrderCount DESC: Ordina i risultati in base al numero di ordini in ordine decrescente (10-1), in modo che il cliente con il maggior numero di ordini sia il primo.

Output:

customer_idorder_count
121415
113514
115612

Questa query restituisce un elenco di clienti che hanno effettuato almeno dieci acquisti l'anno scorso, con il cliente con il maggior numero di ordini in cima ai risultati. La clausola HAVING è importante in questo scenario perché restringe i risultati ai soli clienti fedeli che hanno effettuato più di dieci ordini. Senza la clausola HAVING, la query restituirebbe tutti i clienti, indipendentemente dal numero di ordini.

Esercizio 3: I migliori prodotti in base alle vendite

Esercizio: Il responsabile delle vendite di un negozio di mobili vuole identificare i prodotti con i maggiori incassi. Per i prodotti con vendite superiori a 10.000 dollari, visualizzare l'ID del prodotto e l'importo totale venduto. Inoltre, assicurarsi che i prodotti con le vendite più elevate siano visualizzati in cima ai risultati.

Soluzione:

SELECT product_id, SUM(sales_amount) as total_sales
FROM sales
GROUP BY product_id
HAVING SUM(sales_amount) > 10000
ORDER BY total_sales DESC;

Soluzione Spiegazione:

  • SELECT product_id, SUM(sales_amount) as total_sales: La clausola SELECT visualizza sia l'ID del prodotto che il totale delle vendite.
  • FROM sales: Specifica la tabella di origine come sales.
  • GROUP BY product_id: Raggruppa i dati in base all'ID prodotto, creando un gruppo per ogni prodotto.
  • HAVING SUM(sales_amount) > 10000: La clausola HAVING filtra il set di risultati per includere solo i prodotti con vendite totali superiori a 10.000 dollari.
  • ORDER BY total_sales DESC: Ordina i risultati in base alle vendite totali in ordine decrescente, assicurando che i prodotti con il maggior numero di vendite appaiano per primi.

Risultati:

product_idtotal_sales
10218300
10515600
16012200

Questa query restituisce un elenco dei prodotti più performanti, mostrando i prodotti con vendite superiori a 10.000 dollari e ordinando le righe in ordine decrescente in base alle vendite totali.

La clausola HAVING è necessaria perché ci consente di filtrare il set di risultati utilizzando dati aggregati, in particolare le vendite totali. Senza la clausola HAVING, non sarebbe possibile filtrare i risultati in base alle vendite totali di ciascun prodotto. La clausola WHERE non è adatta a questo compito perché filtra le righe prima del raggruppamento; a noi interessano le condizioni applicate ai dati aggregati dopo il raggruppamento.

Esercizio 4: Valutazione media per genere

Esercizio: Un critico cinematografico vuole identificare i generi di film con valutazioni medie elevate nel 2020. Vi è stato chiesto di visualizzare i generi cinematografici e le valutazioni medie per quei generi che hanno una valutazione superiore a 4.0. Inoltre, assicuratevi che i generi con le valutazioni medie più alte appaiano in cima.

Soluzione:

SELECT genre, AVG(rating) as avg_rating
FROM movies
WHERE YEAR(release_date) = 2020
GROUP BY genre
HAVING AVG(rating) > 4.0
ORDER BY avg_rating DESC;

Spiegazione:

  • SELECT genre, AVG(rating) as avg_rating: La clausola SELECT visualizza il genere di film e la valutazione media.
  • FROM film: specifica la tabella di origine come movies.
  • WHERE YEAR(release_date) = 2020: Filtra le righe per includere solo i film usciti nell'anno 2020.
  • GROUP BY genere: Raggruppa i dati per genere, creando un gruppo per ogni genere.
  • HAVING AVG(rating) > 4.0: Filtra il set di risultati per includere solo i generi con una valutazione media superiore a 4,0.
  • ORDER BY avg_rating DESC: Ordina i risultati per valutazione media in ordine decrescente, assicurando che i generi con le valutazioni medie più alte siano in cima.

Output:

genreavg_rating
Drama4.5
Comedy4.2

Questa query aiuta il critico cinematografico a identificare i generi cinematografici eccezionali con una valutazione media superiore a 4,0 nel 2020. L'insieme dei risultati comprende ogni genere e la sua valutazione media, ordinati in ordine decrescente in base alla valutazione media.

La clausola HAVING è essenziale perché ci permette di filtrare i generi in base ai dati aggregati (la valutazione media).

Esercizio 5: Identificare gli utenti con una durata di accesso prolungata

Esercizio: Utilizzando i dati di accesso degli utenti di un sito web, il team di sicurezza informatica cerca di identificare gli utenti che hanno una durata di accesso singola insolitamente lunga; ciò consente di eseguire un monitoraggio e un'analisi completi della sicurezza. Visualizzate i nomi degli utenti, gli indirizzi e-mail e la durata della loro sessione di accesso singola più lunga. Considerate solo gli utenti i cui tempi di accesso superano le due ore (7200 secondi). Inoltre, assicuratevi che gli utenti con la durata di login più lunga appaiano in cima ai risultati.

Soluzione:

SELECT 
  users.user_name, 
  users.email_address, 
  MAX(logins.login_duration) as longest_login_duration
FROM users
JOIN logins 
ON users.user_id = logins.user_id
GROUP BY users.user_name, users.email_address
HAVING MAX(logins.login_duration) > 7200
ORDER BY longest_login_duration DESC;

Spiegazione:

  • SELECT users.user_name, users.email_address, MAX(logins.login_duration) as longest_login_duration: La clausola SELECT visualizza i nomi degli utenti, gli indirizzi e-mail e la durata della loro singola sessione di accesso più lunga.
  • FROM users: Questa clausola specifica la tabella di origine come users.
  • JOIN logins ON users.user_id = logins.user_id: Esegue un join interno tra le tabelle users e logins in base all'ID utente.
  • GROUP BY users.user_name: Raggruppa i dati in base ai nomi degli utenti, creando un gruppo per ogni utente.
  • HAVING MAX(logins.login_duration) > 7200: La clausola HAVING filtra l'insieme dei risultati, includendo solo gli utenti con una durata di accesso superiore a 2 ore (7200 secondi).
  • ORDER BY longest_login_duration DESC: Ordina i risultati in base alla durata di accesso più lunga, in ordine decrescente.

Output:

user_nameemail_addresslongest_login_duration
marty_89ff_7799@mail.com9067
scott_32scott_oc@mail.com7591
rachel_2003ray_hhh@mail.com7231

Questa query fornisce al team di sicurezza IT i nomi degli utenti, gli indirizzi e-mail e la durata delle loro sessioni di accesso singole più lunghe. La query mostra solo gli utenti con una durata di accesso prolungata per un maggiore controllo della sicurezza.

In questo caso, la clausola HAVING è importante perché ci permette di filtrare l'insieme dei risultati in base ai dati aggregati, in particolare la durata massima di login raggiunta da ciascun utente. Poiché vogliamo identificare gli utenti che hanno effettuato il login per più di due ore, la clausola HAVING ci permette di imporre questa condizione sulla durata massima del login.

Casi d'uso comuni per HAVING

La clausola HAVING in SQL è uno strumento fondamentale negli scenari reali in cui l'analisi dei dati, la reportistica e la business intelligence sono importanti. Vediamo alcuni casi d'uso comuni che dimostrano la versatilità di HAVING.

1. Segmentazione dei clienti

Le aziende traggono vantaggio dalla comprensione dei diversi gruppi di clienti, in modo da poter indirizzare i loro sforzi di marketing. La creazione di segmenti di clienti consente di elaborare strategie su misura, migliorando così la soddisfazione dei clienti.

Utilizzando HAVING, possiamo filtrare i clienti di alto valore in base alle soglie di acquisto:

SELECT customer_id, SUM(purchase_amount) as total_purchase
FROM purchases
GROUP BY customer_id
HAVING SUM(purchase_amount) > 500;

2. Analisi delle prestazioni dei dipendenti

Iprofessionisti delle risorse umane possono utilizzare SQL per valutare le prestazioni dei dipendenti. In questo modo si facilita una valutazione equa e specifica delle prestazioni.

Utilizzando la seguente query, possiamo trovare i dipendenti che hanno completato più di un certo numero di progetti:

SELECT employee_id, COUNT(project_id) as completed_projects
FROM projects
GROUP BY employee_id
HAVING COUNT(project_id) >= 5;

3. Monitoraggio delle vendite dei prodotti

Per garantire una gestione efficiente delle scorte, le aziende devono tenere traccia dei prodotti più performanti. In questo modo è possibile identificare gli articoli più venduti e allocare le risorse in modo più efficace.

Utilizzando la seguente query, possiamo filtrare i prodotti con vendite superiori a una certa soglia:

SELECT product_id, SUM(sales_quantity) as total_sales
FROM sales	
GROUP BY product_id
HAVING SUM(sales_quantity) > 50;

4. Tracciamento delle presenze agli eventi

Gli organizzatori di eventi possono voler identificare i partecipanti più impegnati, ossia quelli che hanno partecipato a più di un evento. La ricerca di informazioni su questi partecipanti può essere utile per la pianificazione di eventi futuri.

L'uso di HAVING nella seguente query ci permette di identificare i partecipanti altamente impegnati in base al loro numero di eventi:

SELECT attendee_id, COUNT(event_id) as attended_events
FROM event_attendance
GROUP BY attendee_id
HAVING COUNT(event_id) > 3;

5. Controllo qualità nella produzione

Nel settore manifatturiero, il controllo della qualità è essenziale per realizzare prodotti di alta qualità. Specificando le soglie nelle query SQL, il team può garantire la qualità dei prodotti.

Utilizzando HAVING nella seguente query, è possibile identificare i prodotti con tassi di difettosità inferiori al limite specificato:

SELECT product_id, AVG(defect_rate) as avg_defect_rate
FROM manufacturing_quality
GROUP BY product_id
HAVING AVG(defect_rate) > 0.02;

Suggerimenti per la risoluzione dei problemi con la clausola HAVING

L'uso della clausola HAVING in SQL può talvolta dare luogo a errori comuni, soprattutto se si è agli inizi. Ecco alcuni suggerimenti per la risoluzione dei problemi:

Ordine delle istruzioni SQL

Quando si inizia a lavorare con le query SQL, è comune commettere errori nell'ordine delle istruzioni. Assicuratevi sempre che la vostra query segua questo ordine:

SELECT column1, COUNT(column2) as count_column2
FROM my_table
WHERE condition
GROUP BY column1
HAVING COUNT(column2) > 10
ORDER BY column1;

Non raggruppare i dati

Quando si usa la clausola HAVING, i dati devono essere prima raggruppati usando la clausola GROUP BY. La seguente query produrrebbe un errore perché non contiene la clausola GROUP BY:

SELECT category, COUNT(product_id) as product_count
FROM products
HAVING COUNT(product_id) > 5;

Incoerenza di SELECT e GROUP BY

La colonna non aggregata nell'istruzione SELECT deve essere inclusa nella clausola GROUP BY. L'esempio seguente dimostra che, poiché la categoria non è aggregata, deve essere inclusa nella clausola GROUP BY.

SELECT category, COUNT(product_id) as product_count
FROM products
GROUP BY category
HAVING COUNT(product_id) > 5;

Uso errato delle condizioni HAVING

La query seguente viene eseguita senza errori, ma non segue le best practice. La clausola HAVING viene utilizzata per filtrare i risultati in base a valori aggregati, quindi l'inclusione di colonne non aggregate o di condizioni non corrette contraddice lo scopo prefissato.

SELECT category, COUNT(product_id) as product_count
FROM products
GROUP BY category
HAVING category = 'Electronics';

Anche se la query viene eseguita correttamente, si consiglia di utilizzare la clausola WHERE per filtrare le colonne non aggregate. In questo modo si rispettano le best practice e si garantisce la chiarezza del codice SQL.

WHERE vs. HAVING

È possibile che si verifichino errori a causa della confusione tra WHERE e HAVING. Per evitarlo, ricordate che WHERE riguarda le righe e HAVING i gruppi.

Nella query precedente con l'errore, si potrebbe usare più appropriatamente WHERE piuttosto che HAVING:

SELECT category, COUNT(product_id) as product_count
FROM products
WHERE category = 'Electronics'
GROUP BY category;

Esclusione delle funzioni aggregate da HAVING

Quando si esegue un filtro basato su valori aggregati, è necessario includere la funzione aggregata nella clausola HAVING. Nell'esempio seguente, product_id dovrebbe essere COUNT(product_id) nella clausola HAVING:

SELECT category, COUNT(product_id)
FROM products
GROUP BY category
HAVING product_id > 5;

Esistono molti altri possibili errori di sintassi SQL. La buona notizia è che, con la pratica, si impara rapidamente a evitarli. Quando si verifica un errore, prestare attenzione al messaggio di errore, che può aiutare a identificare il problema specifico.

Pronti per un po' di pratica con la clausola HAVING di SQL?

La clausola HAVING di SQL è uno strumento prezioso per ottimizzare i risultati delle query nell'analisi dei dati, nei report e nella Business Intelligence. La padronanza di questa clausola consente agli utenti di SQL di estrarre informazioni preziose da dati aggregati.

Nel corso del vostro viaggio in SQL, non abbiate paura di commettere errori durante la scrittura di query con la clausola HAVING: fa parte del processo di apprendimento! La buona notizia è che non siete soli. Su LearnSQL.it è disponibile molto materiale per aiutarvi a padroneggiare la clausola HAVING. Per ulteriori esempi, consultate il nostro Tutorial su SQL HAVING.

Per andare ancora più a fondo, consultate la nostra traccia SQL dalla A alla Z . Copre tutto ciò che SQL ha da offrire, compresa l'importantissima clausola HAVING. Questa traccia consente di combinare le conoscenze teoriche con la pratica, scrivendo le proprie query SQL in una console interattiva e ricevendo un feedback immediato. Cosa state aspettando? Iniziate!