web-dev-qa-db-ja.com

1つのクエリ内の複数のテーブルでの複数の左結合

1つのmasterテーブルがあり、これには複数のレベル(親と子)に格納されたアイテムがあり、追加のデータがある場合とない場合がある2番目のテーブルがあります。マスターテーブルから2つのレベルをクエリし、2番目のテーブルで左結合を行う必要がありますが、クエリ内の順序のためにこれは機能しません。

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'

左結合は、from句の最後のテーブルでのみ機能するため、左結合の1つに対してのみ機能させることができます。上記の例では、最初の左結合がfrom句の最初のテーブルを指しているため、左結合は機能しません。2番目の結合はこのように機能しません。

どうすればこの作品を作ることができますか?

22
DeniseMeander

この種のクエリは動作するはずです-明示的なANSI JOIN構文で書き直した後:

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'

ここでのつまずきは、明示的なJOINが「古いスタイル」CROSS JOINコンマ付き(,)。 ここにマニュアルを引用します:

いずれにしても、JOINは、FROM- list項目を区切るコンマよりも強くバインドします。

最初のものを書き直した後、すべての結合が左から右に適用され(論理的には、Postgresはクエリプランのテーブルを自由に再配置できます)、機能します。

私の主張をするために、これも機能します:

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'

ただし、ケースでもう一度説明するように、一般的には明示的なJOIN構文が望ましいです。

また、複数(左)のJOINで行を乗算できることに注意してください。

36

このようにすることができます

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

JOINステートメントはFROM句の一部でもあり、より正式にはjoin_typeを使用して2つfrom_item 's into onefrom_item -FROMの後に区切られたリスト。 http://www.postgresql.org/docs/9.1/static/sql-select.html を参照してください。

あなたの問題の直接的な解決策は次のとおりです。

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'

すでに提案されているように、JOINのみを使用することをお勧めします。

2
Daniel Sparing