it-swarm.com.de

Mehrere linke Joins für mehrere Tabellen in einer Abfrage

Ich habe eine master Tabelle, in der Elemente in mehreren Ebenen gespeichert sind, Eltern und Kinder, und es gibt eine zweite Tabelle, die möglicherweise zusätzliche Daten enthält oder nicht. Ich muss zwei Ebenen aus meiner Mastertabelle abfragen und einen Left-Join in meiner zweiten Tabelle haben, aber aufgrund der Reihenfolge in meiner Abfrage funktioniert dies nicht.

SELECT something FROM master as parent, master as child
  LEFT JOIN second as parentdata ON parent.secondary_id = parentdata.id
  LEFT JOIN second as childdata ON child.secondary_id = childdata.id
WHERE parent.id = child.parent_id AND parent.parent_id = 'rootID'

Der Left-Join funktioniert nur mit der letzten Tabelle in der from-Klausel, daher kann ich ihn nur für einen der Left-Joins verwenden. Im obigen Beispiel funktioniert keiner der Links-Joins, da der erste Links-Join auf die erste Tabelle in der from-Klausel verweist, der zweite wird niemals so funktionieren.

Wie kann ich das schaffen?

22
DeniseMeander

Diese Art von Abfrage sollte funktionieren - nach dem Umschreiben mit der expliziten ANSI JOIN -Syntax:

SELECT something
FROM   master      parent
JOIN   master      child ON child.parent_id = parent.id
LEFT   JOIN second parentdata ON parentdata.id = parent.secondary_id
LEFT   JOIN second childdata ON childdata.id = child.secondary_id
WHERE  parent.parent_id = 'rootID'

Der Auslösedraht hier ist, dass ein explizites JOIN vor "altem Stil" CROSS JOIN Mit Komma (,) gebunden wird. Ich zitiere das Handbuch hier:

In jedem Fall wird JOIN enger gebunden als die Kommas, die FROM-Listenelemente trennen.

Nach dem Umschreiben der ersten werden alle Verknüpfungen von links nach rechts angewendet (logischerweise kann Postgres Tabellen im Abfrageplan ansonsten frei neu anordnen), und es funktioniert.

Um es klar auszudrücken, würde dies auch funktionieren:

SELECT something
FROM   master parent
LEFT   JOIN second parentdata ON parentdata.id = parent.secondary_id
,      master child
LEFT   JOIN second childdata ON childdata.id = child.secondary_id
WHERE  child.parent_id = parent.id
AND    parent.parent_id = 'rootID'

Aber eine explizite JOIN -Syntax ist im Allgemeinen vorzuziehen, wie Ihr Fall noch einmal zeigt.

Beachten Sie, dass mehrere (LINKE) JOINs Zeilen multiplizieren können:

36

Das kannst du machen

SELECT something
FROM
    (a LEFT JOIN b ON a.a_id = b.b_id) LEFT JOIN c on a.a_aid = c.c_id
WHERE a.parent_id = 'rootID'
4
pradipgarala

Die JOIN -Anweisungen sind auch Teil der FROM -Klausel. Formal wird ein join_type verwendet, um zwei from_item 'zu kombinieren. s into one from_item, von denen mehrere nach dem FROM eine durch Kommas getrennte Liste bilden können. Siehe http://www.postgresql.org/docs/9.1/static/sql-select.html .

Die direkte Lösung für Ihr Problem lautet also:

SELECT something
FROM
    master as parent LEFT JOIN second as parentdata
        ON parent.secondary_id = parentdata.id,
    master as child LEFT JOIN second as childdata
        ON child.secondary_id = childdata.id
WHERE parent.id = child.parent_id AND parent.parent_id = 'rootID'

Eine bessere Option wäre, nur JOIN zu verwenden, wie es bereits vorgeschlagen wurde.

2
Daniel Sparing