2013-01-10 28 views
18

我有一個master表,其中有多個級別存儲的項目,父母和孩子,還有第二個表可能有也可能沒有額外的數據。我需要從我的主表中查詢兩個級別,並在我的第二個表上有一個左連接,但由於我的查詢中的排序,這不起作用。在一個查詢中的多個表上的多個左連接

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子句中的最後一個表,所以我只能使它適用於其中一個左連接。在上面的例子中,沒有任何左連接將工作,因爲第一個左連接指向from子句中的第一個表,第二個將不會像這樣工作。

我該如何做這項工作?

+6

混合「舊式」與「新風貌」(LEFT JOIN(FROM子句中的兩個表的名稱)...ON)幾乎肯定會流淚。重寫一下,並仔細看看你的WHERE子句,這可能會消除你不想被淘汰的行。 –

回答

29

這種查詢應該工作 - 有明確的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用逗號(,)結合。 I quote the manual here:

在任何情況下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語法通常是優選的,因爲你的情況再次說明。

而且要知道,多(左)加入可以成倍行:

2

JOIN陳述也都FROM子句的一部分,更正式一join_type用於將兩個from_item's組合成一個from_item,其中的多個之後可以形成逗號分隔列表r 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的,因爲它已經被提出。

4

你可以這樣做

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' 
+3

@DeniseMeander:我不知道爲什麼這個答案被接受。它不會爲舊問題添加任何新內容,除了括號外,在這種情況下這只是噪聲。也沒有解釋。顯式連接默認從左到右執行(除非連接條件強制執行不同的順序)。 –

+0

@ErwinBrandstetter這個答案更加清晰,因爲你的表名有一些空格,而且很混亂。 – kahonmlg

+1

@kahonmlg:任何表名中都沒有空格。也許你誤解了表的別名。請參閱:https://stackoverflow.com/a/11543614/939860 –