SQL JOIN 完整教學:INNER、LEFT、RIGHT、FULL JOIN 圖解【2025】

SQL JOIN 完整教學:INNER、LEFT、RIGHT、FULL JOIN 圖解【2025】
在實際的資料庫應用中,資料通常分散在多個關聯表格中。例如,客戶資料存在「客戶表」、訂單資料存在「訂單表」、商品資料存在「商品表」。當你需要查詢「某客戶購買了哪些商品」時,就必須將這些表格「連接」起來查詢——這就是 SQL JOIN 的核心用途。
本文將以圖解方式完整介紹 SQL JOIN 的所有類型,搭配實際程式碼範例,幫助你直觀理解每種 JOIN 的差異與使用時機。無論你是剛學習 SQL 的新手,還是想複習 JOIN 語法的開發者,都能從本文獲得清晰的概念。
插圖:SQL JOIN 類型總覽圖,以 Venn Diagram 展示各種 JOIN 的資料選取範圍
場景描述: 並排展示 INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN 四種 JOIN 類型的 Venn Diagram,用不同顏色標示各類型選取的資料範圍。
視覺重點:
- 主要內容清晰呈現
必須出現的元素:
- 依據描述中的關鍵元素
需要顯示的中文字: 無
顏色調性: 專業、清晰
避免元素: 抽象圖形、齒輪、發光特效
Slug:
sql-join-types-venn-diagram-overview
JOIN 概念與使用時機
什麼是 JOIN?
JOIN 是 SQL 中用於合併兩個或多個表格資料的操作。透過指定表格之間的關聯條件(通常是共同的欄位,如外鍵),JOIN 可以將分散的資料整合成一個查詢結果。
範例資料準備
為了清楚說明各種 JOIN 的差異,我們先建立兩個簡單的範例表格:
員工表(Employees):
| EmployeeID | Name | DepartmentID |
|---|---|---|
| 1 | Alice | 101 |
| 2 | Bob | 102 |
| 3 | Carol | 101 |
| 4 | David | NULL |
部門表(Departments):
| DepartmentID | DepartmentName |
|---|---|
| 101 | 研發部 |
| 102 | 行銷部 |
| 103 | 財務部 |
注意:David 沒有指定部門(DepartmentID 為 NULL),而財務部(103)沒有任何員工。
JOIN 類型總覽
| JOIN 類型 | 說明 | 回傳資料 |
|---|---|---|
| INNER JOIN | 內連接 | 只回傳兩表都有匹配的資料 |
| LEFT JOIN | 左外連接 | 回傳左表所有資料 + 右表匹配資料 |
| RIGHT JOIN | 右外連接 | 回傳右表所有資料 + 左表匹配資料 |
| FULL OUTER JOIN | 完全外連接 | 回傳兩表所有資料 |
| CROSS JOIN | 交叉連接 | 回傳兩表的笛卡爾積 |
| Self Join | 自連接 | 表格與自己連接 |
INNER JOIN 內連接
INNER JOIN 是最常用的 JOIN 類型,只回傳兩個表格中都有匹配資料的列。如果某一邊沒有對應的資料,該列就不會出現在結果中。
語法結構
SELECT 欄位列表
FROM 表格A
INNER JOIN 表格B
ON 表格A.關聯欄位 = 表格B.關聯欄位;
圖解說明
表格A 表格B
┌───────┐ ┌───────┐
│ │ │ │
│ ████████████████████ │
│ █ 交集部分 █ │
│ ████████████████████ │
│ │ │ │
└───────┘ └───────┘
INNER JOIN 只回傳交集部分(兩邊都有匹配的資料)
實際範例
-- 查詢所有有部門的員工及其部門名稱
SELECT
e.EmployeeID,
e.Name,
d.DepartmentName
FROM Employees e
INNER JOIN Departments d
ON e.DepartmentID = d.DepartmentID;
查詢結果:
| EmployeeID | Name | DepartmentName |
|---|---|---|
| 1 | Alice | 研發部 |
| 2 | Bob | 行銷部 |
| 3 | Carol | 研發部 |
說明: David 因為沒有部門(DepartmentID 為 NULL),所以不會出現在結果中。財務部因為沒有員工,也不會出現。
使用時機
- 只需要兩個表格中都有對應資料的記錄
- 排除任一表格中沒有匹配的資料
- 例如:查詢「有訂單的客戶」、「已分配部門的員工」
LEFT JOIN 左外連接
LEFT JOIN(或 LEFT OUTER JOIN)回傳左表的所有資料,以及右表中匹配的資料。如果右表沒有匹配,則對應欄位顯示 NULL。
語法結構
SELECT 欄位列表
FROM 表格A
LEFT JOIN 表格B
ON 表格A.關聯欄位 = 表格B.關聯欄位;
圖解說明
表格A 表格B
┌───────┐ ┌───────┐
│███████│ │ │
│███████████████████████ │
│███████ 交集 ████ │
│███████████████████████ │
│███████│ │ │
└───────┘ └───────┘
LEFT JOIN 回傳左表全部 + 交集部分
實際範例
-- 查詢所有員工及其部門(包含沒有部門的員工)
SELECT
e.EmployeeID,
e.Name,
d.DepartmentName
FROM Employees e
LEFT JOIN Departments d
ON e.DepartmentID = d.DepartmentID;
查詢結果:
| EmployeeID | Name | DepartmentName |
|---|---|---|
| 1 | Alice | 研發部 |
| 2 | Bob | 行銷部 |
| 3 | Carol | 研發部 |
| 4 | David | NULL |
說明: David 雖然沒有部門,但因為他在左表(Employees)中,所以會出現在結果中,DepartmentName 顯示為 NULL。
找出沒有匹配的資料
LEFT JOIN 常用於找出「左表有但右表沒有」的資料:
-- 查詢沒有分配部門的員工
SELECT
e.EmployeeID,
e.Name
FROM Employees e
LEFT JOIN Departments d
ON e.DepartmentID = d.DepartmentID
WHERE d.DepartmentID IS NULL;
結果: 只會回傳 David
使用時機
- 需要保留左表所有資料,即使右表沒有對應
- 找出「沒有關聯資料」的記錄
- 例如:查詢「所有客戶及其訂單(含無訂單客戶)」、「所有商品及其銷售記錄(含未銷售商品)」
RIGHT JOIN 右外連接
RIGHT JOIN(或 RIGHT OUTER JOIN)與 LEFT JOIN 相反,回傳右表的所有資料,以及左表中匹配的資料。
語法結構
SELECT 欄位列表
FROM 表格A
RIGHT JOIN 表格B
ON 表格A.關聯欄位 = 表格B.關聯欄位;
圖解說明
表格A 表格B
┌───────┐ ┌───────┐
│ │ │███████│
│ ███████████████████████│
│ ████ 交集 ███████│
│ ███████████████████████│
│ │ │███████│
└───────┘ └───────┘
RIGHT JOIN 回傳交集部分 + 右表全部
實際範例
-- 查詢所有部門及其員工(包含沒有員工的部門)
SELECT
d.DepartmentID,
d.DepartmentName,
e.Name
FROM Employees e
RIGHT JOIN Departments d
ON e.DepartmentID = d.DepartmentID;
查詢結果:
| DepartmentID | DepartmentName | Name |
|---|---|---|
| 101 | 研發部 | Alice |
| 101 | 研發部 | Carol |
| 102 | 行銷部 | Bob |
| 103 | 財務部 | NULL |
說明: 財務部(103)雖然沒有員工,但因為它在右表(Departments)中,所以會出現在結果中。
實務建議
在實務上,大多數開發者偏好使用 LEFT JOIN,因為閱讀順序更直觀(先看主表,再看關聯表)。RIGHT JOIN 通常可以透過調換表格順序改寫成 LEFT JOIN:
-- 以下兩個查詢結果相同
-- 使用 RIGHT JOIN
SELECT * FROM Employees e RIGHT JOIN Departments d ON e.DepartmentID = d.DepartmentID;
-- 改寫為 LEFT JOIN(推薦)
SELECT * FROM Departments d LEFT JOIN Employees e ON d.DepartmentID = e.DepartmentID;
FULL OUTER JOIN 完全外連接
FULL OUTER JOIN 回傳兩個表格的所有資料,無論是否有匹配。沒有匹配的部分顯示 NULL。
語法結構
SELECT 欄位列表
FROM 表格A
FULL OUTER JOIN 表格B
ON 表格A.關聯欄位 = 表格B.關聯欄位;
注意: MySQL 不直接支援 FULL OUTER JOIN,需要使用 UNION 模擬。
圖解說明
表格A 表格B
┌───────┐ ┌───────┐
│███████│ │███████│
│███████████████████████████│
│███████ 交集 ███████│
│███████████████████████████│
│███████│ │███████│
└───────┘ └───────┘
FULL OUTER JOIN 回傳兩個表格的所有資料
實際範例
-- SQL Server / PostgreSQL 語法
SELECT
e.EmployeeID,
e.Name,
d.DepartmentID,
d.DepartmentName
FROM Employees e
FULL OUTER JOIN Departments d
ON e.DepartmentID = d.DepartmentID;
查詢結果:
| EmployeeID | Name | DepartmentID | DepartmentName |
|---|---|---|---|
| 1 | Alice | 101 | 研發部 |
| 2 | Bob | 102 | 行銷部 |
| 3 | Carol | 101 | 研發部 |
| 4 | David | NULL | NULL |
| NULL | NULL | 103 | 財務部 |
MySQL 模擬 FULL OUTER JOIN
-- MySQL 不支援 FULL OUTER JOIN,使用 UNION 模擬
SELECT e.EmployeeID, e.Name, d.DepartmentID, d.DepartmentName
FROM Employees e
LEFT JOIN Departments d ON e.DepartmentID = d.DepartmentID
UNION
SELECT e.EmployeeID, e.Name, d.DepartmentID, d.DepartmentName
FROM Employees e
RIGHT JOIN Departments d ON e.DepartmentID = d.DepartmentID;
使用時機
- 需要完整呈現兩個表格的所有資料
- 分析兩個資料集的差異
- 例如:比對兩個系統的資料完整性
CROSS JOIN 交叉連接
CROSS JOIN 產生兩個表格的笛卡爾積(Cartesian Product),即左表每一列與右表每一列的所有組合。
語法結構
-- 語法一:明確使用 CROSS JOIN
SELECT 欄位列表
FROM 表格A
CROSS JOIN 表格B;
-- 語法二:隱式寫法
SELECT 欄位列表
FROM 表格A, 表格B;
實際範例
-- 產生所有員工與所有部門的組合
SELECT
e.Name,
d.DepartmentName
FROM Employees e
CROSS JOIN Departments d;
查詢結果: 4 名員工 × 3 個部門 = 12 筆結果
| Name | DepartmentName |
|---|---|
| Alice | 研發部 |
| Alice | 行銷部 |
| Alice | 財務部 |
| Bob | 研發部 |
| Bob | 行銷部 |
| Bob | 財務部 |
| ... | ... |
使用時機
- 產生所有可能的組合
- 測試資料生成
- 例如:產生「所有尺寸 × 所有顏色」的商品組合
注意: CROSS JOIN 會產生大量資料(m × n 列),使用時務必謹慎,避免對大型表格使用。
Self Join 自連接
Self Join 是表格與自己連接的特殊應用,用於處理具有層級關係的資料(如員工與主管、分類與子分類)。
範例資料
員工表(含主管欄位):
| EmployeeID | Name | ManagerID |
|---|---|---|
| 1 | Alice | NULL |
| 2 | Bob | 1 |
| 3 | Carol | 1 |
| 4 | David | 2 |
實際範例
-- 查詢每位員工及其主管姓名
SELECT
e.Name AS EmployeeName,
m.Name AS ManagerName
FROM Employees e
LEFT JOIN Employees m
ON e.ManagerID = m.EmployeeID;
查詢結果:
| EmployeeName | ManagerName |
|---|---|
| Alice | NULL |
| Bob | Alice |
| Carol | Alice |
| David | Bob |
使用時機
- 表格中有自我參照的關聯(如 ManagerID 指向同表的 EmployeeID)
- 處理層級結構資料
- 例如:組織架構、商品分類、留言回覆
多表 JOIN 與效能考量
多表 JOIN 語法
實務中經常需要連接三個以上的表格:
-- 查詢訂單明細:客戶名稱、訂單編號、商品名稱
SELECT
c.CustomerName,
o.OrderID,
o.OrderDate,
p.ProductName,
od.Quantity
FROM Customers c
INNER JOIN Orders o ON c.CustomerID = o.CustomerID
INNER JOIN OrderDetails od ON o.OrderID = od.OrderID
INNER JOIN Products p ON od.ProductID = p.ProductID
WHERE o.OrderDate >= '2025-01-01';
JOIN 效能優化建議
| 優化方向 | 說明 |
|---|---|
| 建立索引 | 在 JOIN 欄位(通常是外鍵)建立索引 |
| 先篩選再 JOIN | 使用 WHERE 或子查詢先縮小資料範圍 |
| **避免 SELECT *** | 只選取需要的欄位,減少資料傳輸 |
| 小表驅動大表 | 將資料量小的表格放在 JOIN 左邊 |
| 檢視執行計畫 | 使用 EXPLAIN 分析查詢效能 |
-- 建立索引範例
CREATE INDEX idx_orders_customerid ON Orders(CustomerID);
CREATE INDEX idx_orderdetails_orderid ON OrderDetails(OrderID);
常見問題 FAQ
Q1:LEFT JOIN 和 RIGHT JOIN 有什麼差別?
LEFT JOIN 保留左邊表格的所有資料,RIGHT JOIN 保留右邊表格的所有資料。以 FROM A LEFT JOIN B 為例,即使 B 表沒有對應資料,A 表的資料仍會全部出現,B 表欄位顯示 NULL。反之,FROM A RIGHT JOIN B 會保留 B 表所有資料。實務上,大多數開發者習慣使用 LEFT JOIN,因為閱讀順序更直觀(主表在前)。如果需要 RIGHT JOIN 的效果,可以調換表格順序改用 LEFT JOIN。
Q2:什麼時候應該使用 INNER JOIN?
當你只需要兩個表格中都有對應資料的記錄時,使用 INNER JOIN。例如:查詢「有訂單的客戶」——如果某客戶沒有訂單,你不希望他出現在結果中,就使用 INNER JOIN。相反地,如果你需要「所有客戶,包含沒有訂單的」,就應該使用 LEFT JOIN。簡單判斷:如果你可以接受某些列因為沒有匹配而「消失」,就用 INNER JOIN;如果你需要保留某一邊的完整資料,就用 LEFT/RIGHT JOIN。
延伸學習資源
深入學習 SQL 查詢技巧,建議參考以下資源:
SQL 基礎語法:
- SQL 完整指南:從入門到精通的資料庫查詢語言教學
- SQL 語法大全:SELECT、JOIN、WHERE 完整查詢指令教學
- SQL CRUD 操作完整指南:INSERT、UPDATE、DELETE 語法教學
- SQL 函數完整指南:字串、日期、數學、聚合函數總整理
進階查詢技巧:
結論
SQL JOIN 是資料庫查詢的核心技能,掌握各種 JOIN 類型的差異,能讓你靈活處理各種多表查詢需求。簡單總結:
- INNER JOIN:只要交集,兩邊都有才回傳
- LEFT JOIN:保留左表全部,右表沒有則顯示 NULL
- RIGHT JOIN:保留右表全部,左表沒有則顯示 NULL
- FULL OUTER JOIN:兩邊全部保留
- CROSS JOIN:產生所有組合(笛卡爾積)
- Self Join:表格與自己連接,處理層級關係
建議從 INNER JOIN 和 LEFT JOIN 開始練習,這兩種涵蓋了 90% 以上的實務需求。熟練後再學習其他 JOIN 類型,逐步提升你的 SQL 查詢能力。
想要快速查閱 JOIN 語法? — 下載我們整理的 SQL JOIN 速查圖解,包含所有 JOIN 類型的 Venn Diagram 與語法範例,列印出來放在桌邊隨時參考。
參考資料
- W3Schools SQL JOIN - https://www.w3schools.com/sql/sql_join.asp
- Microsoft SQL JOIN Documentation - https://docs.microsoft.com/sql/t-sql/queries/from-transact-sql
- PostgreSQL JOIN Types - https://www.postgresql.org/docs/current/queries-table-expressions.html
- MySQL JOIN Syntax - https://dev.mysql.com/doc/refman/8.0/en/join.html
相關文章
雲端 SQL 資料庫比較:Azure SQL、Cloud SQL、AWS RDS 完整評比【2025】
全面比較三大雲端 SQL 資料庫服務:Azure SQL Database、Google Cloud SQL、AWS RDS。涵蓋功能特色、高可用性、定價模式、遷移策略,幫助企業選擇最適合的雲端資料庫方案。
SQLSQL CRUD 操作完整指南:INSERT、UPDATE、DELETE 語法教學【2025】
系統性介紹 SQL 資料操作語言(DML)核心指令。涵蓋 INSERT 新增、UPDATE 更新、DELETE 刪除的完整語法,以及 TRUNCATE 差異比較、交易控制、常見錯誤提醒。
SQLSQL 函數完整指南:字串、日期、數學、聚合函數總整理【2025】
SQL 內建函數完整參考手冊。涵蓋字串函數(CONCAT、SUBSTRING、REPLACE)、日期函數(DATEADD、DATEDIFF)、數學函數(ROUND、CEILING)、聚合函數(COUNT、SUM、AVG)的語法與範例。