Vai al contenuto principale

La differenza tra WHERE e HAVING in SQL

Scopri come WHERE filtra i dati a livello di riga nelle query SQL, mentre HAVING filtra i dati raggruppati dopo l’aggregazione, e padroneggia i loro usi distinti nelle interrogazioni SQL.
Aggiornato 3 giu 2026  · 8 min leggi

WHERE e HAVING sono due clausole essenziali in SQL. Che tu stia scrivendo query molto avanzate o molto semplici, ti capiterà di dover usare entrambe. Puoi pensare a WHERE e HAVING come a due fratelli: svolgono una funzione simile (il filtraggio) e spesso compaiono insieme. Ma, proprio come i fratelli, hanno caratteristiche distinte e ruoli specifici. 

Se stai cercando di fare chiarezza tra WHERE e HAVING, ti suggerisco di iscriverti al nostro skill track SQL Fundamentals come ottimo punto di partenza completo. Ti insegnerà le diverse clausole SQL, l’ordine di esecuzione in SQL, come ottimizzare le query SQL e molte altre nozioni fondamentali.  

La risposta breve: WHERE vs. HAVING 

La risposta breve, che è anche la fonte di confusione per molte persone, è che WHERE lavora sui dati a livello di riga, mentre HAVING opera sui dati raggruppati. Ecco una linea guida:

  • WHERE filtra le righe prima che avvenga qualsiasi raggruppamento o aggregazione. Si applica alle singole righe e non può essere usato con funzioni di aggregazione.

  • HAVING filtra i gruppi dopo che il raggruppamento e l’aggregazione sono stati eseguiti. Si applica ai risultati delle funzioni di aggregazione e viene usato in combinazione con GROUP BY.

Un esempio veloce per mostrare la differenza 

Vediamo un esempio rapido. Se vuoi seguire con il tuo workflow, puoi scaricare il dataset sugli affitti di immobili da questo repository GitHub.

Supponiamo ora di dover restituire tutte le proprietà nel nostro dataset che hanno un canone di affitto inferiore a $500. Il livello di dettaglio di ciascuna riga nel dataset (una proprietà per riga) corrisponde al livello di dettaglio della condizione della query. Pertanto, usiamo WHERE nella seguente query:

SELECT *
FROM rentals
WHERE rental_price < 500

Il risultato apparirebbe così. Nota che vengono restituite 118 righe.

Semplice filtraggio di righe con SQL WHERE

Semplice filtraggio di righe con WHERE. Immagine dell’autore.

Supponiamo ora di non voler avere una tabella di proprietà, ma di città che hanno un prezzo medio di affitto inferiore a $2.700. Invece di avere ogni riga corrispondente a una proprietà, raggrupperemo le righe e aggregheremo il canone in un prezzo medio di affitto per ciascuna città. Pertanto, useremo HAVING, come in questa query:

SELECT city, AVG(rental_price) AS average_rent
FROM rentals
GROUP BY city
HAVING AVG(rental_price) < 2700;

E il risultato sarebbe questo. Nota che c’è un solo risultato. 

Semplice filtraggio di gruppi con SQL HAVING

Semplice filtraggio di gruppi con HAVING. Immagine dell’autore.

WHERE, HAVING e ordine di esecuzione in SQL

Vediamo che WHERE lavora con il filtraggio a livello di riga, mentre HAVING lavora con il filtraggio a livello di aggregato. Capire questa differenza spiana anche la strada per imparare l’ordine di esecuzione delle clausole in SQL

WHERE viene valutata prima di GROUP BY e subito dopo FROM (e JOIN se presente); non può gestire alcun raggruppamento o aggregazione. WHERE entra in gioco prima che venga eseguita qualsiasi aggregazione. Per questo opera solo su dati a livello di riga. 

Nel frattempo, HAVING arriva dopo l’esecuzione della clausola GROUP BY. Ciò significa che entra in gioco dopo aver trasformato la tabella e averla raggruppata a un livello diverso dalla granularità della tabella di origine. HAVING opera sulla nuova versione trasformata della tabella. 

Come usare la clausola WHERE in SQL

Facciamo un passo indietro e guardiamo ciascuna clausola singolarmente. Possiamo iniziare con la clausola WHERE.

Sintassi e istruzioni di WHERE

WHERE può essere usata in tre diverse istruzioni SQL: SELECT, UPDATE e DELETE.

WHERE nelle istruzioni SELECT

Nelle istruzioni SELECT, che sono quelle usate per recuperare i dati dal database, WHERE svolge il suo ruolo diretto nel filtraggio a livello di riga e ha il suo posto ben noto subito dopo la clausola FROM, come possiamo vedere nella seguente query:

SELECT column1, column2… etc.
FROM table_name
WHERE condition;

L’uso di WHERE con SELECT è il punto in cui la clausola WHERE viene più spesso confusa con HAVING

WHERE nelle istruzioni UPDATE

Inoltre, WHERE svolge un ruolo importante nelle istruzioni UPDATE per individuare la riga in cui deve avvenire l’aggiornamento dei dati, come possiamo vedere con la seguente sintassi:

UPDATE table_name
SET column_name1 = value1, column_name2 = value2… etc.
WHERE condition;

WHERE nelle istruzioni DELETE

WHERE è anche un’aggiunta utile alle istruzioni DELETE per individuare i record (righe) che devono essere eliminati, come vediamo qui:

DELETE FROM table_name
WHERE condition;

Come scrivere le condizioni WHERE

Le condizioni WHERE sono scritte come semplici espressioni logiche. Sono composte da tre parti: variabile/operando, condizione e valore/risultato. Vediamo le opzioni per le condizioni WHERE, che includono sia operatori di confronto che logici.  

Segno operatore Descrizione Tipo di dato dell’operando
= Uguale a (alla data) Numerico, Testo, Data/timestamp, Booleano
< Minore di (prima della data) Numerico, Data/timestamp
> Maggiore di (dopo la data) Numerico, Data/timestamp
<= Minore o uguale a (alla o prima della data) Numerico, Data/timestamp
>= Maggiore o uguale a (alla o dopo la data) Numerico, Data/timestamp
<> (!=) Diverso da (non alla data) Numerico, Testo, Data/timestamp, Booleano
IN Uguale a più di un valore (in più date) Numerico, Testo, Data/timestamp, Booleano (anche se poco sensato!)
LIKE Corrisponde a un pattern di testo (con wildcard) Testo
BETWEEN Appartiene a un intervallo Numerico, Data/timestamp
AND Combina più condizioni, tutte devono essere vere Logico (Booleano)
OR Combina più condizioni, almeno una deve essere vera Logico (Booleano)
NOT Neghere una condizione Logico (Booleano)
IS NULL Verifica valori null Tutti i tipi di dato
IS NOT NULL Verifica valori non null Tutti i tipi di dato

Ecco un esempio in cui usiamo NOT insieme all’operatore di confronto IN:

SELECT *
FROM rentals
WHERE city NOT IN ('Cairo', 'Giza');

L’istruzione restituirà tutte le proprietà che non si trovano né nella città del Cairo né in quella di Giza.

Uso di NOT con WHERE

Proprietà al di fuori del Cairo e di Giza. Immagine dell’autore.

Casi d’uso di WHERE

Sapendo che WHERE opera con le istruzioni SELECT, UPDATE e DELETE, possiamo prevedere che si presti a tre casi d’uso: filtraggio a livello di riga, recupero dati e manipolazione dei dati.

Filtraggio a livello di riga

Possiamo filtrare le righe della tabella in base a una o più condizioni. La seguente query filtra le righe per includere solo le proprietà di tipo villa.

SELECT *
FROM rentals
WHERE type = ‘villa’;

Uso di NOT con WHERE

Selezione delle proprietà villa. Immagine dell’autore.

Recupero dati

WHERE può essere usata per recuperare un punto dati specifico che stiamo cercando. È simile al filtraggio a livello di riga ma più mirata. Supponendo che ci serva conoscere l’ID della proprietà disponibile il primo gennaio 2022 al Cairo, possiamo usare la seguente query:

SELECT property_id
FROM rentals
WHERE available_date = '2022-01-01'
AND city = 'Cairo';

Filtraggio a livello di riga con WHERE

Recupero di un punto dati. Immagine dell’autore.

Manipolazione dei dati

Infine, WHERE è un grande aiuto per modificare valori ed eliminare record specifici nel tuo database. Per esempio, supponendo di aver scoperto che la proprietà 171 in realtà non ammette animali, possiamo modificare la colonna pet_friendly usando WHERE in un’istruzione UPDATE come segue:

UPDATE rentals
SET pet_friendly = false
WHERE property_id = 171;

Come usare la clausola HAVING in SQL

Ora è il momento di passare alla clausola HAVING con lo stesso livello di dettaglio. 

Sintassi e istruzioni di HAVING

Per prima cosa, dovremmo sapere che la clausola HAVING può essere usata solo nelle istruzioni SELECT. Pertanto, la sua unica sintassi è la seguente:

SELECT grouped_column, aggregate_function(aggregated_column)… etc.
FROM table_name
GROUP BY grouped_column
HAVING condition

Nota che puoi aggiungere più di una colonna di raggruppamento e più di una colonna aggregata. Vedremo esempi più avanti.

Come scrivere le condizioni HAVING

Come WHERE, le condizioni HAVING sono scritte come espressioni logiche, ma con un componente aggiuntivo: la funzione di aggregazione. Quindi, una condizione HAVING è composta da 1) Funzione di aggregazione, 2) variabile/operando, 3) operatore di confronto e 4) valore/risultato.

Funzioni di aggregazione con HAVING

SQL ha principalmente cinque funzioni di aggregazione, più una sesta che è un caso speciale. Queste funzioni sono:

Funzione di aggregazione Tipo di dato adatto
SUM() Numerico
AVG() Numerico
MIN() Numerico, Testo, Data/timestamp
MAX() Numerico, Testo, Data/timestamp
COUNT() Numerico, Testo, Data/timestamp, Booleano

Proviamo un esempio. Qui usiamo la funzione COUNT() con GROUP BY per creare una tabella di frequenza e usiamo la condizione HAVING come filtro. In particolare, ci servono le città citate 150 volte o meno, che in questo contesto hanno a che fare con il numero di registrazioni. Possiamo usare questa query:

SELECT city, COUNT(*) AS properties_count
FROM rentals
GROUP BY city
HAVING COUNT(*) <= 150;

Uso di MAX() con HAVING

Uso di COUNT() con HAVING. Immagine dell’autore.

Operatori di confronto e logici

HAVING accetta tutti gli operatori di confronto e logici che accetta WHERE. L’unica differenza è che il tipo di dato adatto con HAVING dipende innanzitutto dalla funzione di aggregazione, come vediamo nella tabella sopra.

Casi d’uso di HAVING

A differenza di WHERE, HAVING non può essere usata nelle istruzioni UPDATE e DELETE; HAVING è usata solo per il recupero dei dati. In linea di massima, questo si traduce in due scenari:

Filtraggio a livello di gruppo

Questo è l’uso comune e normale di HAVING. Un esempio è restituire solo le città che hanno prezzi medi di affitto inferiori a $2.700.

SELECT city, AVG(rental_price) AS avg_price
FROM rentals
GROUP BY city
HAVING AVG(rental_price) < 2700;

Filtraggio a riga singola

Questo è un caso meno comune, ma HAVING può essere usata per restituire un’aggregazione a riga singola, come una metrica o un KPI, solo se soddisfa una certa condizione. Questo si può ottenere usando HAVING senza GROUP BY. Nel seguente esempio, restituiamo il prezzo medio di affitto solo se è inferiore a $2.800. Se la misura soddisfa la condizione, avremo un risultato a riga singola. In caso contrario, avremo una tabella vuota.

SELECT AVG(rental_price) as avg_price
FROM rentals
HAVING AVG(rental_price) > 2800;

Combinare WHERE e HAVING

WHERE e HAVING possono essere combinati per filtrare le tabelle sia prima che dopo l’aggregazione. Nell’esempio seguente, restituiamo il conteggio delle proprietà in ciascuna città, contando solo le proprietà pet friendly e filtrando solo le città che hanno più di 80 proprietà.

SELECT city, COUNT(*) AS number_properties
FROM rentals
WHERE pet_friendly = true
GROUP BY city
HAVING COUNT(*) > 80;

Combinare WHERE con HAVING

Combinazione di base di WHERE e HAVING. Immagine dell’autore.

La differenza tra WHERE e HAVING in termini di performance

Sappiamo che la clausola WHERE viene applicata prima del raggruppamento o dell’aggregazione. Ma dovremmo anche sapere che, per questo motivo, poiché riduce presto nel corso della query il numero di righe elaborate, WHERE è più efficiente per filtrare le singole righe. 

Sappiamo invece che la clausola HAVING viene applicata dopo l’aggregazione e filtra il result set in base ai dati raggruppati. Per questo motivo, poiché elabora i dati dopo che tutte le righe sono state raggruppate, in genere è meno efficiente di WHERE, pur restando necessaria per condizioni che coinvolgono funzioni di aggregazione.

Guardiamo questa query:

SELECT city, COUNT(*)
FROM rentals
GROUP BY city
HAVING rental_price < 2700;

Questa query è inefficiente perché la condizione su rental_price non dipende da alcuna aggregazione — filtra le singole righe. La query prima raggrupperà tutti gli affitti per città, li conterà e poi filtrerà il risultato, il che è inefficiente perché elabora righe non necessarie. Per questo motivo, questa sarebbe stata una query più veloce:

SELECT city, COUNT(*)
FROM rentals
WHERE rental_price < 2700
GROUP BY city;

Consigli di ottimizzazione per WHERE e HAVING

Sulla base di quanto visto, possiamo trarre alcune buone pratiche per ottimizzare l’uso delle clausole WHERE e HAVING. Questo è importante se hai dataset di grandi dimensioni.

  1. Sii molto selettivo: filtra in base ai valori di cui hai davvero bisogno, e non oltre. Questo aiuterà a ridurre il numero di righe nella vista e quindi a migliorare l’efficienza della query.

  2. Sii semplice: elimina condizioni, aggregazioni e conversioni di tipo non necessarie. Tutti questi extra hanno sicuramente un costo computazionale.

  3. Filtra presto: se stai effettuando un’aggregazione a livello di gruppo, pre-filtra le righe con WHERE per rendere più veloce il processo di raggruppamento. Così facendo, ridurrai il numero di righe da elaborare nel raggruppamento.

Tabella di confronto

Ricapitoliamo i concetti in una tabella pratica:

Confronto WHERE HAVING
Scopo principale Filtraggio a livello di riga Filtraggio a livello di gruppo
Sintassi di base SELECT column1, column2... FROM table_name WHERE condition; SELECT grouped_column, aggregate_function(aggregated_column)... FROM table_name GROUP BY grouped_column HAVING condition;
Ordine di valutazione Prima di GROUP BY Dopo GROUP BY
Istruzioni compatibili SELECT, UPDATE, DELETE  SELECT
Condizioni Non possono includere funzioni di aggregazione Devono includere funzioni di aggregazione
Casi d’uso Filtraggio a livello di riga Recupero dati Manipolazione dei dati Filtraggio a livello di gruppo Filtraggio a riga singola
Sottoquery Può funzionare con sottoquery Devono essere scritte come CTE

Conclusione

In tutto l’articolo abbiamo esplorato la differenza principale tra WHERE e HAVING in SQL, ossia che la clausola WHERE filtra le righe prima dell’aggregazione, mentre la clausola HAVING filtra i dati raggruppati dopo l’aggregazione. Abbiamo anche visto alcune differenze meno note, come il fatto che WHERE può lavorare con le istruzioni SELECT, UPDATE e DELETE, mentre HAVING funziona solo con SELECT. Abbiamo parlato anche un po’ di performance.

La SQL Basics Cheat Sheet di DataCamp offre un’utile sintesi delle clausole WHERE e HAVING e alcune indicazioni su come effettuare il filtraggio in SQL. Inoltre, se stai iniziando con SQL, dai un’occhiata allo skill track SQL Fundamentals e al career track Associate Data Analyst in SQL


Islam Salahuddin's photo
Author
Islam Salahuddin

Islam è un consulente dati presso The KPI Institute. Con un background nel giornalismo, Islam ha interessi diversi, tra cui scrittura, filosofia, media, tecnologia e cultura.

Domande frequenti

Qual è la differenza tra WHERE e HAVING?

WHERE esegue il filtraggio a livello di riga mentre HAVING esegue il filtraggio a livello di gruppo.

Posso combinare WHERE e HAVING in un’unica query?

Sì, ed è altamente consigliato usare WHERE se hai intenzione di usare HAVING.

WHERE può funzionare con funzioni di aggregazione come HAVING?

No, solo HAVING può lavorare con funzioni di aggregazione.

WHERE e HAVING funzionano con gli stessi operatori di confronto e logici?

Sì, entrambe funzionano con gli stessi operatori, poiché le condizioni WHERE e HAVING sono scritte come espressioni logiche.

Posso usare HAVING senza GROUP BY?

HAVING è generalmente usata dopo il raggruppamento con GROUP BY. L’unica eccezione è il filtraggio di viste a valore singolo (come il calcolo di una metrica).

Argomenti

Impara SQL con DataCamp

Corso

Manipolazione dei dati in SQL

4 h
323.5K
Vedi dettagliRight Arrow
Inizia il corso
Mostra altroRight Arrow
Correlato

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Mostra altroMostra altro