Ich bin auf dieses Rätsel in den Kommentaren hier gestoßen
CREATE TABLE r (b INT);
SELECT 1 FROM r HAVING 1=1;
SQL Server und PostgreSQL geben 1 Zeile zurück.
MySQL und Oracle geben keine Zeilen zurück.
Welches ist richtig? Oder sind beide gleich gültig?
aggregate
sql-standard
Martin Smith
quelle
quelle
SELECT COUNT(*) FROM r;
1 Zeile (mit0
) zurückgegeben wird, währendSELECT COUNT(*) FROM r GROUP BY ();
keine Zeilen zurückgegeben werden.SELECT 1 WHERE 1=0 HAVING 1=1;
. SQL Server und PostgreSQL geben weiterhin eine Zeile zurück. Oracle möchte FROM DUAL und gibt keine Zeilen zurück. MySQL kompiliert weder mit noch ohne FROM DUAL .SELECT 1 AS t FROM (SELECT 1) tmp WHERE 1=0 HAVING 1=1;
1-row-no-dual und gibt 0 Zeilen zurück.<group by clause>
,“GROUP BY ()”
ist implizit." Sollten dann nicht beide Abfragen die gleichen Ergebnisse liefern?HAVING
anders aus): SQL-Fiddle 2: HAVING macht die Dinge andersAntworten:
Nach dem Standard:
meint
Zitat ISO / IEC 9075-2: 2011 7.10 Syntaxregel 1 (Teil der Definition der HAVING-Klausel):
Ok, so viel ist ziemlich klar.
Behauptung:
1=1
ist wahre Suchbedingung. Ich werde dafür kein Zitat geben.Jetzt
ist gleichwertig mit
Zitat ISO / IEC 9075-2: 2011 7.10 Allgemeine Regel 1:
Logik: Da die Suchbedingung immer wahr ist
R
, ist das Ergebnis das Ergebnis der Gruppierung nach Ausdrücken.Das Folgende ist ein Auszug aus den Allgemeinen Regeln von 7.9 (die Definition der GROUP BY CLAUSE)
Daraus können wir schließen
ergibt eine gruppierte Tabelle, bestehend aus einer Gruppe, mit null Zeilen (da R leer ist).
Ein Auszug aus den Allgemeinen Regeln von 7.12, in dem eine Abfragespezifikation (auch als SELECT-Anweisung bezeichnet) definiert ist:
Da die Tabelle eine Gruppe enthält, muss sie daher eine Ergebniszeile enthalten.
Somit
sollte eine 1-zeilige Ergebnismenge zurückgeben.
QED
quelle
Wenn es eine
HAVING
Klausel ohneWHERE
Klausel gibt:... dann
GROUP BY ()
ist implizit. Die Abfrage sollte also äquivalent sein zu:... die alle Zeilen der Tabelle in einer Gruppe gruppieren sollte (auch wenn die Tabelle überhaupt keine Zeilen enthält - es ist immer noch eine Gruppe von 0 Zeilen) und 1 Zeile zurückgeben. Die
HAVING
mit derTrue
Bedingung sollte danach überhaupt keine Wirkung haben.Wie viele Zeilen sollte eine solche Abfrage aus einem anderen Blickwinkel zurückgeben?
Eins, Null oder "Null oder Eins, je nachdem, ob die Tabelle leer ist oder nicht"?
Ich denke, eine Zeile, egal wie viele Zeilen
r
hat.quelle
Wie ich sehe, scheinen SQLServer und PostgerSQL überhaupt nicht in die Tabelle zu schauen:
Gibt auch nur eine Zeile zurück. Auch wenn SQLServer docs sagt
Dies ist in diesem Fall nicht der Fall,
WHERE 1=1
sondernHAVING
gibt die richtige Anzahl von Zeilen zurück. Ich würde sagen, es ist ein Optimierungsfehler (oder zumindest ein Dokumentationsfehler) ... Der SQLServer-Plan zeigt "Constant Scan" für den FallHAVING
und "Table Scan" fürWHERE
...Das Verhalten von Oracle und MySQL erscheint mir logischer und korrekter ...
quelle
explain
"Result (rows = 1) ..." für "Seq Scan" für "WHERE" ersehen kann, wird auch nicht in die Tabelle geschaut. Ich denke, es hängt irgendwie damit zusammen, dass "FROM" in TSQL und PostgreSQL nicht obligatorisch ist. Ich weiß, dass Mysql es auch nicht benötigt, aber da sie es unterstützendual
, analysieren sie die Abfrage wahrscheinlich ein bisschen anders. Ich stimme zu, es klingt wie eine Spekulation, aber ich hoffe, dass es einen Sinn ergibt.