Seltsam "alles" in "wo"

8

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?

    
carl 13.07.2012, 00:52
quelle

3 Antworten

8

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:

%Vor%

Deshalb gibt es sowohl 10 als auch 2 von Tabelle t1

zurück

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

zurückgeben

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:

%Vor%

Wenn Sie das DeMorgan-Theorem auf das optimierte SQL von MySql anwenden:

%Vor%

Das entspricht:

%Vor%

Was wiederum dem syntaktischen Zucker ALL entspricht:

%Vor%     
Michael Buen 13.07.2012 01:39
quelle
5

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

%Vor%

Unter den Regeln der dreiwertigen Logik

%Vor%

Diese Zeile sollte also nicht zurückgegeben werden. Siehe die ANSI-Spezifikation , in der eindeutig

angegeben ist
  

Das Ergebnis von " R <comp op> <quantifier> T " wird abgeleitet von   Anwendung der implizierten <comparison predicate> " R <comp op> RT " auf   jede Zeile RT in T :

Daher ist dies keine semantisch gültige Optimierung, wenn T Nullable ist. Der vollständige Abschnitt der Spezifikation wird unten wiedergegeben.

  

8.7

%Vor%
    
Martin Smith 15.07.2012 14:19
quelle
4

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: Ссылка

%Vor%

Die erste Abfrage gibt 0 an alle Zeilen zurück.

%Vor%

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 0 als Ergebnis für die Spalte C1 (es sollte 1 sein) einverstanden bin, applaudiere ich Sql Server für seine Konsistenz.

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: -)

Egal wie süß der syntaktische Zucker 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.

%Vor%

Außerdem ist MAX konsistent unter allen RDBMS:

%Vor%

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

    
Michael Buen 23.05.2017 12:01
quelle

Tags und Links