上週的文章詳細介紹了 SELECT 查詢中的外部聯結。它是一種 JOIN 類型,可以從相關資料表中傳回相符和不相符的列。可惜的是,並不是所有資料庫(DB)供應商都支援它,包括 MySQL。但這沒有關係,因為可以透過結合其他三種 JOIN 類型(即 LEFT、INNER 和 RIGHT 連接)來模擬外部聯結。在本文中,我們將詳細了解 LEFT 和 RIGHT 聯結,以及使用 INNER JOIN 結合它們時,如何變成 OUTER JOIN。
LEFT 聯結
LEFT JOIN 傳回左資料表中的所有列和右資料表中相符的列。如果在右資料表中找不到相符的列,則傳回 NULL。以下是它的語法:
SELECT select_list FROM T1 LEFT JOIN T2 ON join_predicate;
下面的 VEN 圖說明了使用 LEFT JOIN 子句可以從兩個資料表 T1 和 T2 中擷取哪些資料:
RIGHT 聯結
RIGHT JOIN 傳回右資料表中的所有列和左資料表中相符的列。如果在左資料表中找不到相符的列,則傳回 NULL。以下是它的語法:
SELECT select_list FROM T1 RIGHT JOIN T2 ON join_predicate;
下面的 VEN 圖說明了使用 RIGHT JOIN 子句可以從兩個資料表 T1 和 T2 中擷取哪些資料:
結合聯結以模擬 OUTER JOIN
整個整個資料庫社群都知道 MySQL 不支援 FULL OUTER JOIN。這個缺陷的一個常見解決辦法是使用 UNION ALL 結合來自兩個資料表的 LEFT JOIN、INNER JOIN 和 RIGHT JOIN 的三個結果集,並將 join_column IS NULL 條件加到 LEFT 和 RIGHT 聯結。
為了示範如何模擬以上的外部聯結,我們將使用與上週「了解 SQL 外部聯結」文章中相同的專案管理資料庫編寫查詢,但這次是在 MySQL 中。
在左資料表中尋找不相符的記錄
第一個查詢將傳回僅在左資料表中找到的列。以下的查詢搭配使用 LEFT 聯結與 WHERE 子句來實現此效果,該子句指定右資料表中的共同(聯結)欄為 NULL:
在第二個資料表中尋找不相符的記錄
第二個查詢將傳回僅在右資料表中找到的列。為此,我們將搭配使用 RIGHT 聯結與 WHERE 子句,該子句指定左資料表中的共同(聯結)欄為 NULL:
在兩個資料表中尋找相符的記錄
若要尋找出現在兩個資料表中的記錄,我們可以使用標準(INNER)JOIN,如下所示:
當使用 UNION ALL 結合這三個獨立的查詢時,會產生與 OUTER JOIN 相同的結果:
總結
在本文中,我們學習了更多有關 LEFT 和 RIGHT 聯結的知識,以及當使用 INNER JOIN 結合它們時,如何變成 OUTER JOIN。和上週一樣,有一件要注意的事情。當與 ORDER BY 和/或 LIMIT 查詢一起使用時,這種方法在查詢大型資料表時可能效率非常低,因為它使用檔案排序(filesort)。在這種情況下,你可能需要採用另一種方法。