多個內部連接返回什麼交集?
如果我有疑問:
SELECT * FROM A INNER JOIN B ON B.ID = A.ID INNER JOIN C ON C.ID = B.ID
這是否會為此查詢返回不同的結果?
SELECT * FROM A INNER JOIN B ON B.ID = A.ID INNER JOIN C ON C.ID = A.ID
在我看來,在第一個查詢中,我會得到 A、B、C 的交集。在第二個查詢中,我會得到 A、B 的交集和 A、C 的交集。
如果是這種情況,我會在 B/C 的列中找到 NULL 值,而 B、C 之間沒有交集嗎?
不,這兩個查詢是相同的。
既然
A.ID = B.ID
和A.ID = C.ID
,那麼根據定義B.ID = C.ID
。對於任何給定的 ID x,如果在
A
ID 中有一行,在 ID 中有一行B
,但在 ID 中沒有行C
,則來自A
and的B
行將被忽略,因為兩個連接都是INNER JOIN
s。當然,對於A-C-B
和也是如此。B-C-A
因此,當所有
JOIN
s 都是INNER JOIN
s時,獲取給定列的唯一方法NULL
是該列是否NULL
在現有行中 - 您不能NULL
在一個表中填寫 s 行,因為沒有匹配的行,因為缺少一個INNER JOIN
ed 表中的匹配行表示其他表中的行無效。換句話說 - 對於 中的給定行
B
,如果 中沒有匹配的行,那麼使用該行C
的行也沒有匹配。該行(以及與其匹配的任何行)將不包括在內,因為所有**ed tables都必須存在一行。A JOIN B``B``B``A
INNER JOIN
A INNER JOIN B RIGHT OUTER JOIN C
如果查詢是或,您詢問是否有任何變化A LEFT OUTER JOIN B INNER JOIN C
。它可以改變。
在正常情況下,連接將從左到右進行評估(即從第一個列出的連接到最後一個連接)。
如果由於某種原因您必須修改該行為,您可以通過移動
ON
子句的位置來實現。根據您的 DBMS,您可能還必須添加括號來指示應評估子句的順序(我嘗試了 MS SQL 和 MySQL;MySQL 需要括號才能工作,MS SQL 允許但不需要它們)。我在下面的範例中包含了括號,這些括號不會從左到右進行評估,以幫助說明這一點。例子:
A INNER JOIN B ON <condition1> RIGHT OUTER JOIN C ON <condition2>
這將首先連接
A
和B
(需要匹配<condition1>
以關聯兩個表中的行),然後執行右外連接到C
(將返回C
滿足WHERE
條件的所有行,並將與A-B
連接中的任何行相關聯<condition2>
滿足。
A INNER JOIN (B RIGHT OUTER JOIN C ON <condition1>) ON <condition2>
另一方面,這將連接 B 和 C(包括來自 的所有
C
符合WHERE
子句的行,與來自該的B
任何行相關聯和基於 的匹配行。請注意,在這裡,您將得到不同的結果和,因為所有行都將具有非 NULL ,但在沒有來自 的匹配行的情況下將為 NULL 。<condition1>``B-C``A``A``B-C``<condition2>``A.id - B.id``A.id = C.id``C.id``B.id``B
A LEFT JOIN B ON <condition1> INNER JOIN C ON <condition2>
對於
ON
通常位置的子句,這是從左到右評估的。因此,首先我們從 中獲取所有行A
,將它們與B
基於<condition1>
;的任何匹配行相關聯。然後,我們對與 的連接結果進行內部連接A-B
,C
僅返回其中一行 from與基於的行A-B
匹配的行。C``<condition2>
A LEFT JOIN (B INNER JOIN C ON <condition1>) ON <condition2>
在這裡,我們再次強制
B-C
內部連接首先發生,因此當來自B
的行與來自的行匹配時,我們會得到行C
based on<condition1>
; 然後,我們獲取B-C
內部連接的結果並將其匹配到A
(從 中返回所有行A
,以及B-C
基於<condition2>
ON
這是幾個 SQLFiddle 連結,它們顯示了當您在子句中移動時這些連接的結果:一個用於MySQL,一個用於MS SQL Server。注意:我沒有說這如何與非 ANSI 連接語法一起工作。如果你不知道我在說什麼 - 感謝你的幸運星並繼續前進。我不確切知道優先級如何與該語法一起使用。我希望它能夠通過表格列表,從左到右(首先提到到最後)。顯然,由於沒有
ON
條款,因此這些條款沒有影響。可能有辦法強制那裡的順序(也許又是括號,大概在FROM
子句中?),但我不知道答案。由於大多數人(包括我自己)強烈建議不要嘗試為您JOIN
的 s 使用該語法,我將簡單地使用它來避免這個問題:-)。