Das Problem existiert in der neuesten Version von MySQL, daher bezweifle ich, dass dies ein Fehler sein könnte.
Hier sind zwei Tabellen:
%Vor%Ausführen:
%Vor%Ergebnismenge zurückgeben:
%Vor%Nach meinem Wissen und der Seite Ссылка
Die Anweisung sollte leeres Ergebnis zurückgeben! Weil jedes Urteil in "wo" zu null führt, wie folgt:
%Vor%gibt zurück:
%Vor% und tatsächlich select id from t1 where null;
gibt nichts zurück!
Schließlich habe ich Folgendes versucht:
%Vor% %Vor%1 Reihe im Satz (0.00 sec)
Wir können sehen, dass MySQL das ursprüngliche SQL auf dieses optimiert, das tatsächlich zum Resultset passt.
aber ich denke nicht, dass das optimierte SQL dem Original entspricht.
Bin ich falsch?
Update : Nach weiterer Analyse und Entfaltung der MySQL > ALL
odd-Implementierung. Diese Antwort sollte als MySQL-spezifisch betrachtet werden. Für einen weiteren Haftungsausschluss ist die Erklärung zur Antwort in Bezug auf > ALL
nicht auf andere RDBMS anwendbar (es sei denn, es gibt andere RDBMS, die die MySQL-Implementierung kopiert haben). Die interne Übersetzung von > ALL
in ein MAX
-Konstrukt gilt nur für MySQL.
Dies:
%Vor%ist semantisch äquivalent zu:
%Vor% Da select max(id) from t2
1 zurückgibt, materialisiert sich die zweite Abfrage wie folgt:
Deshalb gibt es sowohl 10
als auch 2
von Tabelle t1
Einer der Fälle, in denen NULL-Regeln angewendet werden, ist, wenn Sie NOT IN
verwenden, ein Beispiel:
DDL:
%Vor%Abfrage:
%Vor% Die letzten beiden Abfragen geben 10
und 2
zurück, während die ersten beiden Abfragen die leere Menge
Live-Test: Ссылка
Ich hoffe, diese Beispiele löschen Ihre Verwirrung mit NULL-Regeln.
Betreffend
aber ich denke nicht, dass die optimierte sql der ursprünglichen entspricht.
Optimierte SQL ist dies:
%Vor% Das entspricht Ihrer ursprünglichen Abfrage: select id from t1 where id > all (select id from t2);
Das Konstrukt t1.field > all (select t2.field from t2)
ist nur ein syntaktischer Zucker für:
Wenn Sie das DeMorgan-Theorem auf das optimierte SQL von MySql anwenden:
%Vor%Das entspricht:
%Vor% Was wiederum dem syntaktischen Zucker ALL
entspricht:
Dies ist ein Fehler in MySQL ( hier gemeldet und verifiziert ).
Das Update wird in 5.6.7 (neben 5.6x Version) sowie in der nächste Hauptbaum (5.7x)
Es unterscheidet sich vom angegebenen Verhalten in den MySQL-Dokumenten und dem im ANSI-Standard vorgeschrieben.
Außerdem ist es in MySQL nicht einmal konsistent und Sie erhalten andere Ergebnisse, wenn die Unterabfrage auf eine Tabelle verweist, verglichen mit der Unterabfrage, die (die gleichen) Literalwerte enthält.
%Vor% Das zweite Verhalten ist korrekt für die Spezifikation. Wie 10 > ALL( (0),(null),(1) )
sollte wie folgt logisch ausgewertet werden
Unter den Regeln der dreiwertigen Logik
%Vor%Diese Zeile sollte also nicht zurückgegeben werden. Siehe die ANSI-Spezifikation , in der eindeutig
angegeben istDas Ergebnis von "
R <comp op> <quantifier> T
" wird abgeleitet von Anwendung der implizierten<comparison predicate>
"R <comp op> RT
" auf jede ZeileRT
inT
:
Daher ist dies keine semantisch gültige Optimierung, wenn T
Nullable ist. Der vollständige Abschnitt der Spezifikation wird unten wiedergegeben.
8.7
%Vor%
Update (2012-07-15) Das Problem ist nur auf MySQL beschränkt, vielleicht war ich verwirrt, als ich zwischen vielen sqlfiddle-Tabs in Chrome Tab-Tabs verwendete. Es gibt kein Problem mit Postgresql, sein NULL-Verhalten ist sowohl in der SELECT- als auch in der WHERE-Klausel konsistent, ebenso wie in Sql Server.
Adamant, ich bin so verwirrt wie du jetzt, Ich habe deine MySql-Abfrage auf Sql Server versucht: Ссылка
Die erste Abfrage gibt 0
an alle Zeilen zurück.
Natürlich sollte die zweite Abfrage (die eine WHERE-Klausel enthält) keine Zeilen zurückgeben. Welcher Sql Server rechtmäßig tut. Obwohl ich nicht mit einverstanden bin, applaudiere ich Sql Server für seine Konsistenz. 0
als Ergebnis für die Spalte C1
(es sollte 1
sein)
Dann auf Ihrer MySql-Abfrage sowohl auf MySql ( Ссылка ) als auch auf Postgresql ( Ссылка ):
%Vor% MySql und Postgresql ergaben beide die gleiche Ausgabe:
MySql ergibt diese Ausgabe:
%Vor% Ich glaube, dass die zweite Abfrage die richtige Ausgabe hat, aber die eingebettete Bedingung für die SELECT-Klausel (erste Abfrage) zeigt das Gegenteil an. Ich mag diese Inkonsistenz nicht.
Striked Absatzänderung : MySQL hat das Problem. Die Postgresql-Implementierung ist korrekt, sowohl die SELECT-Klausel als auch die WHERE-Klausel liefern das gleiche Ergebnis, sie geben NULL bei SELECT zurück und geben eine leere Zeile in der WHERE-Klausel zurück.
Nun wollte ich diese Frage in Postgresql oder MySql Foren stellen, warum Diskrepanzen zwischen einer Bedingung in der WHERE-Klausel und einer in die SELECT-Klausel eingebetteten Bedingung bestehen.
Ich hoffe, es gibt eine verwandte Seele im Stackoverflow, die diese Inkonsistenz für uns weiter erklären kann: -)
ALL
ist, ich bin nicht geneigt ihn zu benutzen. Es hat ein inkonsistentes Ergebnis zwischen einer WHERE-Klausel und einer eingebetteten SELECT-Anweisung. Ich benutze MAX
trotzdem für alle meine Anfragen, IMHO ist die Absicht klarer als Englisch-wie ALL
, der Grund, warum ich MAX
weiter verwenden muss:
Striked Absatzänderung : Wir sollten keine Abneigung gegen ALL
entwickeln, nur weil MySQL eine fehlerhafte Implementierung hat; -)
Sowohl auf MySql als auch auf PostgreSQL liefert MAX die gleiche Ausgabe
%Vor% Die Ausgabe MAX
ist in beiden RDBMS konsistent.
Außerdem ist MAX
konsistent unter allen RDBMS:
Live-Test:
Um das herauszufinden, implementiert nur MySQL id > ALL
in id > (SELECT MAX
. PostgreSQL und Sql Server interpretieren id > ALL(0,NULL,1)
als id > 0 AND id > NULL AND id > 1
, daher liefern sowohl Postgresql als auch Sql Server dieselbe Ausgabe.
Die Illumination bei NULL-Regeln stammt von Martin Smiths Einblicken in NULL-Werte sind ausgeschlossen. Warum?
Das MySQL-Problem ALL
ist nur für MySQL isoliert, es ist sehr inkonsistent. MySQL übersetzt ALL
in MAX
in seiner WHERE-Klausel; während in seiner SELECT-Klausel MySQL übersetzt ALL
in verkettete ANDs.
Andere RDBMSes implementieren > ALL
als verkettete ANDs, Regeln für NULL on ALL-Ausdrücke gelten sowohl für ihre SELECT- als auch ihre WHERE-Klausel, sie haben konsistente Ergebnisse sowohl für die SELECT- als auch für die WHERE-Klausel. Und ihre Regeln für NULL
auf ALL
sind ANSQL SQL-konform