2015-10-30 8 views
5

Wir können die HAVING-Klausel in der SQL-Abfrage verwenden, um Gruppen von Zeilen zu filtern. Wenn wir die GROUP BY-Klausel verwenden, funktioniert dies direkt auf diese Weise.Wie funktioniert die HAVING-Klausel wirklich?

Aber, lassen Sie uns auf diese Frage suchen:

select 1 where 1!=1 having count(*)=0; 

(oder hängen Sie ihn mit 'von Dual' für Oracle).

Wenn HAVING wirklich Gruppenfilterung macht, nach WHERE haben wir keine Zeilen, also haben wir keine Gruppe und das Ergebnis muss 'Keine Zeile ausgewählt' sein.

Aber in PostgreSQL, MySQL und Oracle erhalten wir '1' als Ergebnis der Abfrage.

Frage: Wie funktioniert HAVING wirklich?

SQL Fiddle für den Test: http://www.sqlfiddle.com/#!15/d5407/51

+0

Dumme Weise zu erkennen, ob eine Tabelle 0 Zeilen hat oder nicht ... – jarlh

+0

WHERE Rückkehr 0 Zeilen, also haben wir 0 Gruppen von Zeilen.Wenn HAVING nur die Gruppenfiltration filtert, warum wird dann gestartet und eine Auswertung für die leere Eingabe durchgeführt? – potapuff

Antwort

7

Wenn es keine ist GROUP BY ein Aggregat immer eine Zeile zurückgibt, in Ihrem Fall die COUNT(*) kehrt 0.

Diese Spalte ist nicht in Ihrer Select-Liste, aber die hartcodierte wörtlichen 1

select count(*) where 1!=1 ; 
select 'bla' where 1!=1 having count(*)=0; 

Siehe fiddle

+0

Ok, wenn HAVING ohne GROUP BY immer eine Zeile zurückgibt, welche Daten diese Zeile enthält? – potapuff

+0

@potapuff: Wenn es keine übereinstimmende Zeile gibt, gibt 'COUNT' null zurück,' SUM', 'MIN', usw. NULL. – dnoeth

3

HAVING ohne GROUP BY cluase gültig ist, und arbeitet auf ganze Tabelle. Von SQL Standard-92:

7,10

:: = MIT

Syntaxregeln

1) Lassen HC das sein. Sei TE das, das sofort HC enthält.

Wenn TE nicht sofort enthält, dann ist GROUP BY() implizit.

und:

:: = GROUP BY

<grouping specification> ::= 
<grouping column reference> 
    | <rollup list> 
    | <cube list> 
    | <grouping sets list> 
    | <grand total> 
    | <concatenated grouping> 

<grouping set> ::= 
<ordinary grouping set> 
    | <rollup list> 
    | <cube list> 
    | <grand total> 

<grand total> ::= <left paren> <right paren> 

Wie Sie GROUP BY() sehen als grand total behandelt.

In Ihrem Beispiel Sie haben:

select 1 
where 1!=1 
having count(*)=0; 

wie eigentlich etwas ist:

select 1 
where 1!=1 
-- group by() 
having count(*)=0; 
+0

Die meisten Datenbanken (MySQL, PostgreSQL, Oracle) unterstützen übrigens GROUP BY() :) – potapuff

Verwandte Themen