Qual è la differenza tra HAVING e WHERE?


261

Devo cercare su Google nel modo sbagliato o sto vivendo un momento stupido nel tempo.

Qual è la differenza tra HAVINGe WHEREin una SQL SELECTdichiarazione?

EDIT: Ho contrassegnato la risposta di Steven come quella corretta in quanto conteneva il bit chiave di informazioni sul link:

Quando GROUP BYnon viene utilizzato, HAVINGsi comporta come una WHEREclausola

La situazione che avevo visto WHEREnel non aveva GROUP BYed è dove la mia confusione è iniziata. Certo, fino a quando non lo sai non puoi specificarlo nella domanda.


44
La linea che citi non è affatto il bit chiave. Il bit chiave, come ha sottolineato wcm , è che HAVINGè un filtro post-aggregazione, mentre WHEREè un filtro pre-aggregazione.
Nick Chammas,

questo link mi ha aiutato a capirlo meglio di tutti i commenti qui sotto, ho
Lijin Durairaj

Risposte:


94

HAVING specifica una condizione di ricerca per un gruppo o una funzione aggregata utilizzata nell'istruzione SELECT.

fonte


369

IN ESSERE: viene utilizzato per verificare le condizioni dopo l'aggregazione.
DOVE: viene utilizzato per verificare le condizioni prima che abbia luogo l'aggregazione.

Questo codice:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City

Ti dà una tabella di tutte le città in MA e il numero di indirizzi in ogni città.

Questo codice:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Having Count(1)>5

Ti dà una tabella delle città in MA con più di 5 indirizzi e il numero di indirizzi in ogni città.


7
Questa dovrebbe essere la risposta accettata. La distinzione tra "avere" e "dove" lo rende immediatamente chiaro.
Paul,

27

La differenza numero uno per me: se HAVINGfosse rimosso dal linguaggio SQL, la vita andrebbe avanti più o meno come prima. Certamente, una query di minoranza dovrebbe essere riscritta usando una tabella derivata, CTE, ecc. Ma sarebbe probabilmente più facile da capire e mantenere come risultato. Forse il codice di ottimizzazione dei fornitori dovrebbe essere riscritto per tener conto di ciò, ancora una volta un'opportunità di miglioramento nel settore.

Ora considera per un momento la rimozione WHEREdalla lingua. Questa volta la maggior parte delle query esistenti dovrebbe essere riscritta senza un ovvio costrutto alternativo. I programmatori dovrebbero diventare creativi, ad esempio il join interno di una tabella nota per contenere esattamente una riga (ad esempio DUALin Oracle) utilizzando la ONclausola per simulare la WHEREclausola precedente . Tali costruzioni sarebbero inventate; sarebbe ovvio che mancava qualcosa nella lingua e di conseguenza la situazione sarebbe peggiorata.

TL; DR potremmo perdere HAVINGdomani e le cose non sarebbero andate peggio, forse meglio, ma lo stesso non si può dire WHERE.


Dalle risposte qui, sembra che molte persone non si rendano conto che una HAVINGclausola può essere usata senza una GROUP BYclausola. In questo caso, la HAVINGclausola viene applicata all'intera espressione della tabella e richiede che nella SELECTclausola compaiano solo le costanti . In genere la HAVINGclausola coinvolgerà aggregati.

Questo è più utile di quanto sembri. Ad esempio, considerare questa query per verificare se la namecolonna è univoca per tutti i valori in T:

SELECT 1 AS result
  FROM T
HAVING COUNT( DISTINCT name ) = COUNT( name );

Sono possibili solo due risultati: se la HAVINGclausola è vera, il risultato sarà una singola riga contenente il valore 1, altrimenti il ​​risultato sarà l'insieme vuoto.


Sarebbe equivalente a "SELEZIONA COUNT (nome DISTINCT) = COUNT (nome) DA T"?
MSpreij,

@MSpreij Non so se funziona per te, ma non funziona su SQL Server 2005 ma il primo lo fa
Joe

22

La clausola HAVING è stata aggiunta a SQL perché non è stato possibile utilizzare la parola chiave WHERE con le funzioni di aggregazione.

Dai un'occhiata a questo link w3schools per ulteriori informazioni

Sintassi:

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value

Una query come questa:

SELECT column_name, COUNT( column_name ) AS column_name_tally
  FROM table_name
 WHERE column_name < 3
 GROUP 
    BY column_name
HAVING COUNT( column_name ) >= 3;

... può essere riscritto usando una tabella derivata (e omettendo il HAVING) in questo modo:

SELECT column_name, column_name_tally
  FROM (
        SELECT column_name, COUNT(column_name) AS column_name_tally
          FROM table_name
         WHERE column_name < 3
         GROUP 
            BY column_name
       ) pointless_range_variable_required_here
 WHERE column_name_tally >= 3;

3
Hai leggermente perso il punto: è HAVINGstato aggiunto perché le tabelle derivate non erano state aggiunte al linguaggio e fino a quando non erano SQL non era completo relazionalmente e una volta erano inevitabilmente HAVINGridondanti.
onedayquen

21

La differenza tra i due sta nella relazione con la clausola GROUP BY:

  • DOVE viene prima di GROUP BY; SQL valuta la clausola WHERE prima di raggruppare i record.

  • HAVING viene dopo GROUP BY; SQL valuta HAVING dopo aver raggruppato i record.

seleziona diagramma delle istruzioni

Riferimenti


Poiché GROUP BY e HAVING sono entrambi opzionali, il diagramma mostra entrambi i casi, basta seguire le frecce.
Paul Sweatte,

Query di esempio dalla mia risposta a questa domanda: SELECT 1 AS result FROM T HAVING...- nel tuo diagramma non riesco a farlo HAVINGsenza passare, GROUP BYma la mia query perfettamente valida e utile non ha GROUP BY. Punto minore: non hai la possibilità di includere valori letterali nella SELECTclausola.
giorno

@onedaywhen Dato che conosci l'implicito GROUP BY, perché non l'hai menzionato? Sai se questo comportamento è quello che ti aspetti o no?
Paul Sweatte,

Pensa che mi stai citando fuori contesto. La domanda riguardava l'apparente deviazione di mySQL dallo standard, tutti tranne l'ultimo paragrafo della mia risposta descrive il comportamento standard e l'ultimo allude alla "clausola GROUP BY implicita menzionata in altre risposte ". Stai dicendo che il tuo diagramma è destinato a descrivere (tutti) i comportamenti impliciti? Non sarebbe più utile attenersi solo al codice che è necessario scrivere per ottenere il comportamento desiderato?
Onedayquen

... Non so a quale comportamento stai alludendo nel secondo link. Il risultato desiderato è correggere il diagramma per mostrare il percorso (esplicito) valido che ho citato. Pensaci: il diagramma copre un'intera query ma la domanda è interessata solo alla WHERE->HAVINGparte, quindi penso che meriti una grande attenzione ai dettagli. Se ritieni che la mia risposta sia sbagliata, modificala o pubblica una correzione suggerita nei commenti.
Onedayquen

12

HAVINGviene utilizzato quando si utilizza un aggregato come GROUP BY.

SELECT edc_country, COUNT(*)
FROM Ed_Centers
GROUP BY edc_country
HAVING COUNT(*) > 1
ORDER BY edc_country;

8

DOVE viene applicato come limitazione sul set restituito da SQL; utilizza le oeprazioni e gli indici dei set predefiniti di SQL ed è quindi il modo più veloce per filtrare i set di risultati. Usa sempre DOVE quando possibile.

HAVING è necessario per alcuni filtri aggregati. Filtra la query DOPO che sql ha recuperato, assemblato e ordinato i risultati. Pertanto, è molto più lento di DOVE e dovrebbe essere evitato tranne nelle situazioni che lo richiedono.

SQL Server ti consente di cavartela usando HAVING anche quando DOVE sarebbe molto più veloce. Non farlo


Il supporto per le tabelle derivate in linguaggio SQL indica che l'affermazione "HAVING è necessario per alcuni filtri aggregati" è falsa.
giorno

1
È un buon punto. Nei tre anni trascorsi da quando ho scritto questa risposta sono sicuramente migrato verso l'utilizzo di tabelle derivate in cui in precedenza avrei usato HAVING. Non ho pensato alla domanda se HAVING abbia ancora alcuni casi d'uso che hanno senso. Inoltre non so se una tabella derivata funzionerà universalmente meglio di HAVING.
davidcl,

7

La clausola WHERE non funziona per le funzioni aggregate
significa: non dovresti usare come questo bonus: nome della tabella

SELECT name  
FROM bonus  
GROUP BY name  
WHERE sum(salary) > 200  

QUI Invece di usare la clausola WHERE devi usare HAVING ..

senza utilizzare la clausola GROUP BY, la clausola HAVING funziona come la clausola WHERE

SELECT name  
FROM bonus  
GROUP BY name  
HAVING sum(salary) > 200  

4

Differenza b / w WHEREe HAVINGclausola:

La differenza principale tra WHEREe la HAVINGclausola è, WHEREviene utilizzata per le operazioni di riga e HAVINGviene utilizzata per le operazioni di colonna.

Perché abbiamo bisogno della HAVINGclausola?

Come sappiamo, le funzioni aggregate possono essere eseguite solo su colonne, quindi non possiamo utilizzare le funzioni aggregate nella WHEREclausola. Pertanto, usiamo le funzioni aggregate nella HAVINGclausola.


2

Quando GROUP BYnon viene utilizzato, le clausole WHEREe HAVINGsono essenzialmente equivalenti.

Tuttavia, quando GROUP BYviene utilizzato:

  • La WHEREclausola viene utilizzata per filtrare i record da un risultato. Il filtro si verifica prima di creare qualsiasi raggruppamento.
  • La HAVINGclausola viene utilizzata per filtrare i valori di un gruppo (ovvero, per verificare le condizioni dopo l'esecuzione dell'aggregazione in gruppi).

Risorsa da qui


avendo e dove non sono essenzialmente equivalenti. darà errore durante l'esecuzione. non è valido nella clausola HAVING perché non è contenuto né in una funzione aggregata né nella clausola GROUP BY.
Nagendra Kumar,

2

Un modo di pensarci è che la clausola having è un filtro aggiuntivo alla clausola where.

Una clausola WHERE viene utilizzata per filtrare i record da un risultato. Il filtro si verifica prima che vengano creati eventuali raggruppamenti. Una clausola HAVING viene utilizzata per filtrare i valori di un gruppo


1

In una query aggregata, (Qualsiasi query in cui viene utilizzata una funzione aggregata) I predicati in una clausola where vengono valutati prima della generazione del set di risultati intermedi aggregato,

I predicati in una clausola Avere vengono applicati al set di risultati aggregato DOPO che è stato generato. Ecco perché le condizioni predicate sui valori aggregati devono essere inserite nella clausola Avendo, non nella clausola Where, e perché è possibile utilizzare gli alias definiti nella clausola Select in una Clausola Have, ma non in una Clausola Where.


1

Ho avuto un problema e ho scoperto un'altra differenza tra WHEREe HAVING. Non agisce allo stesso modo su colonne indicizzate.

WHERE my_indexed_row = 123 mostrerà le righe ed eseguirà automaticamente un "ORDER ASC" su altre righe indicizzate.

HAVING my_indexed_row = 123 mostra tutto, dalla riga "inserita" più vecchia a quella più recente, nessun ordine.


Come fai a sapere che questa è una differenza definita tra i due, piuttosto che un incidente di implementazione del particolare server SQL che stavi utilizzando?
JdeBP,

L'ho appena testato su MariaDB. Immagino che sia stato il server SQL che stavo usando 8 anni fa a produrre risultati diversi.
Simmoniz,

0

Da qui .

lo standard SQL richiede che HAVING debba fare riferimento solo alle colonne nella clausola GROUP BY o alle colonne utilizzate nelle funzioni di aggregazione

al contrario della clausola WHERE che viene applicata alle righe del database


La fonte dice "L'uso delle posizioni delle colonne è deprecato perché la sintassi è stata rimossa dallo standard SQL". Purtroppo, questo è sbagliato: nulla è mai stato rimosso dallo standard, il che ironicamente è il motivo per cui abbiamo ancora HAVINGdecenni dopo che è stato "deprecato" dalle tabelle derivate.
giorno

Leggermente pedante ma la citazione non è corretta, ad esempio prendere in considerazione SELECT 1 FROM T HAVING COUNT(*) >= 1;- non fa riferimento alle colonne nella GROUP BYclausola (non ce ne sono) né alle colonne nelle funzioni aggregate (la query non fa riferimento a nessuna colonna).
giorno

0

Mentre lavoravo a un progetto, questa era anche la mia domanda. Come indicato sopra, HAVING verifica la condizione sul risultato della query già trovato. Ma DOVE serve per controllare le condizioni mentre la query è in esecuzione.

Vorrei fare un esempio per illustrare questo. Supponiamo di avere una tabella di database come questa.

usertable {int userid, date datefield, int dailyincome}

Supponiamo che le seguenti righe siano nella tabella:

1, 2011-05-20, 100

1, 2011-05-21, 50

1, 2011-05-30, 10

2, 2011-05-30, 10

2, 2011-05-20, 20

Ora, vogliamo ottenere se useride di sum(dailyincome)chisum(dailyincome)>100

Se scriviamo:

SELEZIONA userid, somma (dailyincome) DA userable DOVE somma (dailyincome)> 100 GROUP BY userid

Questo sarà un errore. La query corretta sarebbe:

SELEZIONA userid, somma (reddito giornaliero) DAL GRUPPO userable PER userid HAVING somma (reddito giornaliero)> 100


0

La clausola WHERE viene utilizzata per confrontare i valori nella tabella di base, mentre la clausola HAVING può essere utilizzata per filtrare i risultati delle funzioni di aggregazione nel set di risultati della query Fare clic qui !


0

Quando GROUP BY non viene utilizzato, le clausole WHERE e HAVING sono sostanzialmente equivalenti.

Tuttavia, quando si utilizza GROUP BY:

  • La clausola WHERE viene utilizzata per filtrare i record da un risultato. Il filtro si verifica prima che vengano creati eventuali raggruppamenti.
  • La clausola HAVING viene utilizzata per filtrare i valori di un gruppo (ovvero, per verificare le condizioni dopo che è stata eseguita l'aggregazione in gruppi).

-1

Uso HAVING per limitare una query in base ai risultati di una funzione aggregata. EG seleziona * nel gruppo blahblahblah da QUALCOSA avendo il conteggio (QUALCOSA)> 0


-1

Può darsi che l'oggetto di "dove" sia una riga, mentre l'argomento di "avere" è un gruppo. Ho ragione?


3
Dovresti essere sicuro prima di pubblicare una risposta. Questo potrebbe essere fuorviante per gli altri.
pippin1289,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.