SQL ANSI JOIN Vorrang

7

Ich habe eine Abfrage, die so aussieht:

    SELECT *
      FROM TBLA A
 LEFT JOIN TBLB B ON A.Col1 = B.Col2
RIGHT JOIN TBLC C ON B.Col3 = C.Col4
      JOIN TBLD D ON C.Col5 = D.Col6

In welcher Reihenfolge werden die Verknüpfungen aufgelöst? Ich interessiere mich am meisten für SQL Server und werde eine Erklärung dafür als Antwort markieren, interessiere mich aber auch für den ANSI / ISO-Standard und dessen Funktionsweise in den verschiedenen RDBMS.

Der Grund für diese Frage war herauszufinden, warum sich die Ergebnisse von dieser Abfrage unterschieden

    SELECT *
      FROM TBLA A
CROSS JOIN TBLC C
 LEFT JOIN TBLB B ON A.Col1 = B.Col2 AND B.Col3 = C.Col4
      JOIN TBLD D ON C.Col5 = D.Col6
孔夫子
quelle
CROSS JOIN TBLC C in Ihrer zweiten Abfrage unterscheidet sich stark von RIGHT JOIN TBLC C in Ihrer ersten Abfrage. Das allein ist ein großer Unterschied.
AK
1
Mischen LEFTund RIGHT JOINin der gleichen Abfrage bittet um Verwirrung, IMHO.
Jon of All Trades

Antworten:

8

Logischerweise werden die Verknüpfungen in der Reihenfolge der ONKlauseln von links nach rechts aufgelöst.

Die Ausgabe jedes Joins ist eine virtuelle Tabelle, die in den nächsten Join eingeht.

Für die Abfrage in Ihrer Frage wird dann das Ergebnis der virtuellen Tabelle von A LJ Bdirekt mit verbunden C. Die Verknüpfungsbedingung von B.Col3 = C.Col4verliert alle erweiterten Nullzeilen, die durch die ursprüngliche linke Verknüpfung erhalten wurden, und verwandelt die erste Verknüpfung effektiv wieder in eine innere Verknüpfung. Die resultierende virtuelle Tabelle (von der alle Zeilen erhalten bleiben C) wird dann mit der inneren Verknüpfung verknüpft D.

So kann Ihre anfängliche Abfrage als vereinfacht werden

SELECT *
FROM TBLA A
INNER JOIN TBLB B ON A.Col1 = B.Col2
RIGHT JOIN TBLC C ON B.Col3 = C.Col4
      JOIN TBLD D ON C.Col5 = D.Col6

Welches ist effektiv das gleiche wie (A IJ B) ROJ (C IJ D)

Die Reihenfolge der ONKlauseln entspricht nicht unbedingt der Reihenfolge, in der die Tabellen in der Abfrage angezeigt werden. Dies könnte auch umgeschrieben werden als(C IJ D) LOJ (A IJ B)

SELECT *
FROM   TBLC C
       INNER JOIN TBLD D
         ON C.Col5 = D.Col6
       LEFT JOIN TBLA A
                 INNER JOIN TBLB B
                   ON A.Col1 = B.Col2
         ON B.Col3 = C.Col4 

Die Position der on-Klauseln bedeutet, dass der äußere Join zwischen den beiden virtuellen Tabellen ausgeführt wird, die aus (C IJ D)und (A IJ B)nicht nur aus einer einzelnen Tabelle resultieren .

In Ihrer zweiten konzeptionellen Abfrage wird die virtuelle Tabelle konzeptionell A x Cmit B verknüpft, wobei das gesamte kartesische Produkt erhalten bleibt. Das Ergebnis wird dann Dmit dem Prädikat verknüpft C.Col5 = D.Col6. Dies eliminiert alle Zeilen aus dem Endergebnis, die keine innere Verbindung zwischen Cund Dbedeuten, dass es äquivalent zu ist

SELECT *
FROM   TBLC C
       JOIN TBLD D
         ON C.Col5 = D.Col6
       CROSS JOIN TBLA A
       LEFT JOIN TBLB B
         ON A.Col1 = B.Col2
            AND B.Col3 = C.Col4 
Martin Smith
quelle
Ich bin mir nicht sicher, ob der erste ist (A IJ B) ROJ (C IJ D). Ich denke es ist ((A IJ B) ROJ C) IJ D).
Ypercubeᵀᴹ
Diese beiden Versionen sind in den Ergebnissen gleichwertig, jedoch nicht syntaktisch.
Ypercubeᵀᴹ
3

In PostgreSQL:

Verwenden Sie gegebenenfalls Klammern, um die Reihenfolge der Verschachtelung zu bestimmen. In Abwesenheit von Klammern werden JOINs von links nach rechts verschachtelt. In jedem Fall bindet JOIN enger als die Kommas, die FROM-Elemente trennen.

http://www.postgresql.org/docs/9.1/static/sql-select.html#SQL-FROM

dezso
quelle