外部聯結包含 LEFT JOIN
和 RIGHT JOIN
。
MySQL 實作
如下A
LEFT JOIN B
join_specification
將資料表
B
設定為依賴資料表A
以及A
依賴的所有資料表。將資料表
A
設定為依賴LEFT JOIN
條件中使用的所有資料表(除了B
之外)。LEFT JOIN
條件會用來決定如何從資料表B
擷取資料列。(換句話說,不會使用WHERE
子句中的任何條件。)會執行所有標準聯結最佳化,但資料表一定會在依賴的所有資料表之後讀取除外。如果有循環依賴,就會發生錯誤。
會執行所有標準
WHERE
最佳化。如果
A
中有一個符合WHERE
子句的資料列,但B
中沒有符合ON
條件的資料列,就會產生一個額外的B
資料列,其中所有資料行都設定為NULL
。如果您使用
LEFT JOIN
來尋找某些資料表中不存在的資料列,且WHERE
部分有下列測試:
,其中col_name
IS NULLcol_name
是宣告為NOT NULL
的資料行,MySQL 會在找到一個符合LEFT JOIN
條件的資料列之後,停止搜尋更多資料列(針對特定的索引鍵組合)。
RIGHT JOIN
的實作類似於 LEFT JOIN
,只是資料表角色反轉。右聯結會轉換為對等的左聯結,如第 10.2.1.10 節,「外部聯結簡化」中所述。
對於 LEFT JOIN
,如果產生的 NULL
資料列的 WHERE
條件始終為 false,LEFT JOIN
會變更為內部聯結。例如,如果 t2.column1
為 NULL
,則下列查詢中的 WHERE
子句會為 false
SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;
因此,將查詢轉換為內部聯結是安全的
SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;
在準備階段,會移除由常數文字表達式產生的無意義 WHERE
條件,而不是在稍後的優化階段才移除,屆時聯結已經簡化。提早移除無意義條件可讓優化器將外部聯結轉換為內部聯結;這可以改善在 WHERE
子句中包含無意義條件的外部聯結查詢的計畫,例如這個查詢。
SELECT * FROM t1 LEFT JOIN t2 ON condition_1 WHERE condition_2 OR 0 = 1
現在,優化器在準備階段會看到 0 = 1 永遠為 false,因此 OR 0 = 1
是多餘的,並將其移除,剩下這個:
SELECT * FROM t1 LEFT JOIN t2 ON condition_1 where condition_2
現在,優化器可以將查詢重寫為內部聯結,如下所示:
SELECT * FROM t1 JOIN t2 WHERE condition_1 AND condition_2
現在,如果這樣做可以產生更好的查詢計畫,則優化器可以在表 t1
之前使用表 t2
。若要提供有關表聯結順序的提示,請使用優化器提示;請參閱第 10.9.3 節「優化器提示」。或者,使用 STRAIGHT_JOIN
;請參閱第 15.2.13 節「SELECT 陳述式」。但是,STRAIGHT_JOIN
可能會因為禁用半聯結轉換而導致無法使用索引;請參閱使用半聯結轉換優化 IN 和 EXISTS 子查詢謂詞。