Ist die Join-Reihenfolge in SQL wichtig?


189

Erhalte ich unabhängig von der Leistung das gleiche Ergebnis aus Abfrage A und B unten? Wie wäre es mit C und D?

-- A
select *
from   a left join b
           on <blahblah>
       left join c
           on <blahblan>


-- B
select *
from   a left join c
           on <blahblah>
       left join b
           on <blahblan>  

-- C
select *
from   a join b
           on <blahblah>
       join c
           on <blahblan>


-- D
select *
from   a join c
           on <blahblah>
       join b
           on <blahblan>  

11
Was ist <blahblah>? Verbinden Sie A mit B und A mit C oder verbinden Sie A mit B und B mit C?
Beny23

2
Hallo Beny, der Code in meiner Frage ist eine Abstraktion. Ich bin nicht besorgt darüber, A zu B oder A zu C zu verbinden, ich möchte nur wissen, ob die Syntax so identische Ergebnisse liefert.
Nur ein Lernender

Antworten:


225

Bei INNERJoins spielt die Reihenfolge keine Rolle. Die Abfragen geben dieselben Ergebnisse zurück, solange Sie Ihre Auswahl von SELECT *in ändern SELECT a.*, b.*, c.*.


Für ( LEFT, RIGHToder FULL) OUTERJoins ist die Reihenfolge wichtig - und ( aktualisierte ) Dinge sind viel komplizierter.

Erstens sind äußere Verknüpfungen nicht kommutativ, also a LEFT JOIN bnicht dasselbe wieb LEFT JOIN a

Äußere Verknüpfungen sind ebenfalls nicht assoziativ. In Ihren Beispielen, die beide Eigenschaften (Kommutativität und Assoziativität) beinhalten:

a LEFT JOIN b 
    ON b.ab_id = a.ab_id
  LEFT JOIN c
    ON c.ac_id = a.ac_id

ist äquivalent zu :

a LEFT JOIN c 
    ON c.ac_id = a.ac_id
  LEFT JOIN b
    ON b.ab_id = a.ab_id

aber:

a LEFT JOIN b 
    ON  b.ab_id = a.ab_id
  LEFT JOIN c
    ON  c.ac_id = a.ac_id
    AND c.bc_id = b.bc_id

ist nicht gleichbedeutend mit :

a LEFT JOIN c 
    ON  c.ac_id = a.ac_id
  LEFT JOIN b
    ON  b.ab_id = a.ab_id
    AND b.bc_id = c.bc_id

Ein weiteres (hoffentlich einfacheres) Assoziativitätsbeispiel. Stellen Sie sich das vor als (a LEFT JOIN b) LEFT JOIN c:

a LEFT JOIN b 
    ON b.ab_id = a.ab_id          -- AB condition
 LEFT JOIN c
    ON c.bc_id = b.bc_id          -- BC condition

Dies ist gleichbedeutend zu a LEFT JOIN (b LEFT JOIN c):

a LEFT JOIN  
    b LEFT JOIN c
        ON c.bc_id = b.bc_id          -- BC condition
    ON b.ab_id = a.ab_id          -- AB condition

nur weil wir "schöne" ONBedingungen haben. Beide ON b.ab_id = a.ab_idund c.bc_id = b.bc_idsind Gleichstellungsprüfungen und beinhalten keine NULLVergleiche.

Sie können sogar Bedingungen mit anderen oder komplexeren Operatoren wie: ON a.x <= b.xoder ON a.x = 7oder ON a.x LIKE b.xoder haben, ON (a.x, a.y) = (b.x, b.y)und die beiden Abfragen wären immer noch gleichwertig.

Wenn jedoch eine dieser IS NULLFunktionen oder eine Funktion, die sich auf Nullen bezieht, wie COALESCE()z. B. wenn die Bedingung erfüllt ist b.ab_id IS NULL, sind die beiden Abfragen nicht gleichwertig.


3
Es ist richtiger zu sagen, dass der äußere Join assoziativ ist, solange kein Prädikat von einer Zeile erfüllt werden kann, in der alle Spalten einer Tabelle NULL sind, als zu sagen, dass er assoziativ ist, solange die Prädikate nicht IS NULL oder enthalten 'Eine Funktion, die sich auf Nullen bezieht'. Man kann sich leicht ein Prädikat vorstellen, das die erstere Beschreibung erfüllt, aber nicht die letztere, wie a.somecol > 0 OR b.someothercol > 0; Die Assoziativität könnte für diese Bedingung fehlschlagen.
Mark Amery

Aber ja, ich denke, es ist technisch richtig zu sagen, dass OUTER JOIN assoziativ ist, solange das Prädikat keine der hier beschriebenen Bedingungen erfüllt: stackoverflow.com/questions/20022196/… (das erste bricht auch die Assoziativität für INNER JOINs, aber es ist ein so billiger und offensichtlicher Ansatz, es zu brechen, dass es vielleicht nicht erwähnenswert ist.) Es ist auch erwähnenswert, dass die häufigste Art von JOIN - JOINing auf einem Fremdschlüssel - keine dieser Bedingungen erfüllt und ist daher nett und assoziativ.
Mark Amery

1
@ MarkAmery Danke, es fiel mir schwer, meine Sätze in diesem Punkt zu strukturieren (und ich habe Ihre Antwort bereits positiv bewertet;)
ypercubeᵀᴹ

ypercube ich habe eine INNER JOINund eine folge LEFT JOIN. Funktioniert es so, dass zuerst die Abfrage Filterdie Datensätze auf der Basis von INNER JOINund dann LEFT JOINauf die FilteredDatensätze angewendet wird?
Muhammad Babar

In der Tat kommen alle Typen sind assoziativ, wie sie in der SQL - Standard spezifiziert und nach mathematischen Definitionen der Assoziativität, aber sie nicht erscheinen assoziativ , weil Neuanordnung der Klammern erfordert die beweglichen ONKlausel (dh die „Join - Spezifikation“) an einen neuen Standort . Dies ist jedoch nur die Syntax. Wenn Sie die relationale Algebra-Notation verwenden (wobei die Join-Spezifikation unter dem Join-Operator steht), wird die Assoziativität deutlicher. Ihr Argument zeigt nur, dass äußere Verknüpfungen nicht kommutativ sind , was richtig ist
Lukas Eder

4

Bei regulären Joins ist dies nicht der Fall. TableA join TableBerstellt den gleichen Ausführungsplan wie TableB join TableA(Ihre C- und D-Beispiele wären also dieselben)

für links und rechts verbindet es. TableA left Join TableBist anders als TableB left Join TableA, ABER es ist das gleiche alsTableB right Join TableA


4
Dies betrifft nur die Kommutativität, aber die Beispiele in der Frage zeigen, dass der Fragesteller an Assoziativität interessiert ist. Die Antwort von ypercube spricht beide an.
Mark Amery

2

Wenn Sie versuchen, C auf einem Feld von B aus zu verbinden, bevor Sie B beitreten, dh:

SELECT A.x, A.y, A.z FROM A 
   INNER JOIN C
       on B.x = C.x
   INNER JOIN b
       on A.x = B.x

Ihre Abfrage schlägt fehl. In diesem Fall ist die Reihenfolge von Bedeutung.


Ja das ist richtig, die richtige Antwort sollte geändert werden.
Nir Pengas

-2

Oracle-Optimierer wählt die Verknüpfungsreihenfolge der Tabellen für die innere Verknüpfung. Das Optimierungsprogramm wählt die Verknüpfungsreihenfolge von Tabellen nur in einfachen FROM-Klauseln aus. Sie können die Orakel-Dokumentation auf ihrer Website überprüfen. Und für den linken, rechten äußeren Join ist die am häufigsten gewählte Antwort richtig. Der Optimierer wählt die optimale Verknüpfungsreihenfolge sowie den optimalen Index für jede Tabelle. Die Verknüpfungsreihenfolge kann sich darauf auswirken, welcher Index die beste Wahl ist. Das Optimierungsprogramm kann einen Index als Zugriffspfad für eine Tabelle auswählen, wenn es sich um die innere Tabelle handelt, nicht jedoch, wenn es sich um die äußere Tabelle handelt (und es keine weiteren Qualifikationen gibt).

Das Optimierungsprogramm wählt die Verknüpfungsreihenfolge von Tabellen nur in einfachen FROM-Klauseln aus. Die meisten Verknüpfungen, die das Schlüsselwort JOIN verwenden, werden in einfache Verknüpfungen reduziert, sodass das Optimierungsprogramm die Verknüpfungsreihenfolge auswählt.

Das Optimierungsprogramm wählt nicht die Verknüpfungsreihenfolge für äußere Verknüpfungen aus. Es verwendet die in der Anweisung angegebene Reihenfolge.

Bei der Auswahl einer Verknüpfungsreihenfolge berücksichtigt das Optimierungsprogramm: Die Größe jeder Tabelle Die für jede Tabelle verfügbaren Indizes Ob ein Index für eine Tabelle in einer bestimmten Verknüpfungsreihenfolge nützlich ist Die Anzahl der Zeilen und Seiten, die für jede Tabelle in jeder Tabelle gescannt werden sollen Beitrittsreihenfolge

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.