SQL-Standard bezüglich linker äußerer Verbindung und Bedingungen

7

Ich erhalte unterschiedliche Ergebnisse basierend auf einer Filterbedingung in einer Abfrage basierend auf dem Ort, an dem ich die Filterbedingung anlege. Meine Fragen sind:

  • Gibt es einen technischen Unterschied? zwischen diesen Abfragen?
  • Gibt es irgendwas im SQL-Standard? Das erklärt das Andere Recordsets aus den Abfragen?

Angesichts des vereinfachten Szenarios:

%Vor%

Ich ging davon aus, dass die Abfragen die gleichen Resultsets zurückgeben würden, und ich war überrascht, wenn dies nicht der Fall war. Ich benutze MS SQL2005 und in den tatsächlichen Abfragen, Abfrage 1 zurückgegeben ~ 700 Zeilen und Abfrage 2 zurückgegeben ~ 1100 Zeilen und ich konnte kein Muster erkennen, auf dem Zeilen zurückgegeben wurden und welche Zeilen ausgeschlossen wurden. In Abfrage 1 gab es noch viele Zeilen mit untergeordneten Zeilen mit Daten und NULL-Daten. Ich bevorzuge den Stil von Abfrage 2 (und ich denke, es ist optimaler), aber ich dachte, die Abfragen würden die gleichen Ergebnisse zurückgeben.

Bearbeiten / Zusammenfassung:

Hier wurden einige großartige Antworten gegeben. Es fiel mir schwer zu entscheiden, wem ich die Antwort geben sollte. Ich entschied mich, mit mdma zu gehen, da es die erste Antwort und eine der klarsten war. Basierend auf den gelieferten Antworten, hier ist meine Zusammenfassung:

Mögliche Ergebnisse:

  • A: Eltern ohne Kinder
  • B: Eltern mit Kindern
  • | - & gt; B1: Eltern mit Kindern, bei denen kein Kind zu dem Filter
  • passt
  • \ - & gt; B2: Eltern mit Kindern, bei denen 1 oder mehr dem Filter entsprechen

Abfrageergebnisse:

  • Abfrage 1 gibt (A, B2)
  • zurück
  • Abfrage 2 gibt (A, B1, B2)
  • zurück

Abfrage 2 gibt wegen des linken Joins immer ein übergeordnetes Element zurück. In Abfrage 1 wird die WHERE-Klausel nach dem linken Join ausgeführt, sodass Eltern mit Kindern ausgeschlossen werden, bei denen keine der untergeordneten Elemente dem Filter entspricht (Fall B1).

Hinweis: Nur Elterninformationen werden in Fall B1 zurückgegeben, und in Fall B2 werden nur die Eltern- / Kindinformationen zurückgegeben, die mit dem Filter übereinstimmen.

HLGEM hat einen guten Link zur Verfügung gestellt:

Ссылка

    
Ryan 21.05.2010, 14:43
quelle

7 Antworten

9

Die erste Abfrage gibt Fälle zurück, in denen der Elternteil keine Kinder hat oder wo einige Kinder die Filterbedingung erfüllen. Insbesondere Fälle, in denen der Elternteil ein Kind hat, aber nicht mit der Filterbedingung übereinstimmt, werden weggelassen.

Die zweite Abfrage gibt eine Zeile für alle Eltern zurück. Wenn die Filterbedingung nicht übereinstimmt, wird für alle Spalten von c ein NULL-Wert zurückgegeben. Aus diesem Grund erhalten Sie in Abfrage 2 mehr Zeilen - Eltern mit Kindern, die nicht mit der Filterbedingung übereinstimmen, werden mit NULL-Kindwerten ausgegeben, wobei in der ersten Abfrage diese herausgefiltert werden.

    
mdma 21.05.2010, 14:46
quelle
10

Ja, es gibt einen großen Unterschied. Wenn Sie Filter in der ON-Klausel auf einem LINKEN JOIN platzieren, wird der Filter angewendet, bevor die Ergebnisse mit der äußeren Tabelle verknüpft werden. Wenn Sie einen Filter in der WHERE-Klausel anwenden, geschieht dies, nachdem der LEFT JOIN angewendet wurde.

Kurz gesagt, die erste Abfrage schließt Zeilen mit untergeordneten Zeilen aus, aber die untergeordnete Beschreibung entspricht nicht der Filterbedingung, während die zweite Abfrage immer eine Zeile für das übergeordnete Element zurückgibt.

    
Thomas 21.05.2010 14:48
quelle
3

Wenn Sie die Bedingung in die where-Klausel setzen, wird sie in einen inneren Join konvertiert (es sei denn, Sie verwenden etwas, wo id null ist und Sie Datensätze erhalten, die nicht in der Tabelle enthalten sind). Sehen Sie dies für eine ausführlichere Erklärung:

Ссылка

    
HLGEM 21.05.2010 15:17
quelle
2

Für dieses Recordset:

%Vor%

, die erste Abfrage würde 0 records zurückgeben, während die zweite Abfrage 1 record:

zurückgeben würde %Vor%

Jetzt WHERE -Klausel hinzufügen:

%Vor%

WHERE -Klausel filtert die Datensätze, die im vorherigen Schritt zurückgegeben wurden, und kein Datensatz entspricht der Bedingung.

Während dieser:

%Vor%

gibt einen einzelnen falschen Datensatz zurück.

    
Quassnoi 21.05.2010 14:56
quelle
1

Die Eltern, die nur Kinder mit description != 'FilterCondition' haben, werden in Abfrage 1 nicht angezeigt, da die WHERE-Klausel nach dem Verbinden der Zeilen ausgewertet wird.

    
Vincent Malgrat 21.05.2010 14:50
quelle
1

Die erste Abfrage gibt weniger Zeilen zurück, da nur Zeilen zurückgegeben werden, die keine untergeordneten Elemente haben oder untergeordnete Elemente haben, die der Filterbedingung entsprechen.

Die WHERE-Klausel schließt den Rest aus (diejenigen, die untergeordnete Elemente haben, aber nicht mit der Filterbedingung übereinstimmen).

Die zweite Abfrage zeigt alle drei obigen Bedingungen.

    
LesterDove 21.05.2010 14:50
quelle
0

Ich bemerke einige Unterschiede, die die Ergebnisse variieren können. In der ersten Abfrage haben Sie LEFT OUTER JOIN Child c ON (p.ID = c.ParentID) und dann in der zweiten Abfrage LEFT OUTER JOIN Child c ON (p.ID = c.ParentID AND c.Description = 'FilterCondition') und dies bewirkt, dass die zweite Abfrage alle Eltern mit Kindern zurückgibt, die Ihre Bedingung erfüllen wo als erste Bedingung auch die Eltern wit keine Kinder zurückgeben werden. Sehen Sie sich auch den Vorrang von Join-Bedingungen und Bedingungen an.

    
Srikar Doddi 21.05.2010 14:48
quelle

Tags und Links