☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
sql 中級

LEFT / RIGHT / FULL JOIN

為什麼需要 OUTER JOIN?

INNER JOIN 只回傳兩邊都有配對的資料。 但如果你想看到所有學生(包含沒選課的),就需要 OUTER JOIN。


LEFT JOIN

LEFT JOIN = 左邊的表全部保留,右邊沒配對的填 NULL。

SELECT
    s.Name AS 學生,
    c.Name AS 課程,
    e.Score AS 分數
FROM Students s                    -- ← 左表:全部保留
LEFT JOIN Enrollments e            -- ← 右表:有配對的才連
    ON s.Id = e.StudentId
LEFT JOIN Courses c
    ON e.CourseId = c.Id;

結果:

 學生 | 課程 | 分數
------+------+------
 小明 | 數學 |   85
 小明 | 英文 |   92
 小華 | 數學 |   78
 小美 | NULL | NULL    ← 小美沒有選課,但還是出現了!
Students        Enrollments
┌────┐          ┌────┐
│ 小明│─────────▶│ 記錄│  ✅ 有配對
│ 小華│─────────▶│ 記錄│  ✅ 有配對
│ 小美│──── ✗    │    │  ⚠️ 沒配對,但左表保留,右邊填 NULL
└────┘          └────┘

用 LEFT JOIN 找出「沒有」的資料

-- 找出沒有選任何課的學生
SELECT s.Name
FROM Students s
LEFT JOIN Enrollments e ON s.Id = e.StudentId
WHERE e.Id IS NULL;          -- ← 右表是 NULL = 沒有配對 = 沒選課

逐行解析:

LEFT JOIN Enrollments e      -- 左連接,保留所有學生
    ON s.Id = e.StudentId    -- 嘗試配對
WHERE e.Id IS NULL           -- 配對失敗的(e.Id 是 NULL)
                             -- = 在 Enrollments 裡找不到這個學生
                             -- = 這個學生沒有選課

💡 這是 LEFT JOIN 最常見的用法之一:找出「缺少關聯」的資料。


RIGHT JOIN

RIGHT JOIN = 右邊的表全部保留,左邊沒配對的填 NULL。

-- 查詢所有課程(包含沒人選的)
SELECT s.Name AS 學生, c.Name AS 課程
FROM Students s
RIGHT JOIN Enrollments e ON s.Id = e.StudentId
RIGHT JOIN Courses c ON e.CourseId = c.Id;
 學生 | 課程
------+------
 小明 | 數學
 小華 | 數學
 小明 | 英文
 NULL | 物理    ← 物理沒人選,但還是出現了

💡 實務上 RIGHT JOIN 很少用。你可以把表的順序反過來,用 LEFT JOIN 代替:

-- 這兩個完全等價:
A RIGHT JOIN B ON ...  =  B LEFT JOIN A ON ...

FULL OUTER JOIN

FULL JOIN = 兩邊都全部保留,沒配對的填 NULL。

SELECT s.Name AS 學生, c.Name AS 課程
FROM Students s
FULL OUTER JOIN Enrollments e ON s.Id = e.StudentId
FULL OUTER JOIN Courses c ON e.CourseId = c.Id;
 學生 | 課程
------+------
 小明 | 數學
 小明 | 英文
 小華 | 數學
 小美 | NULL    ← 小美沒選課
 NULL | 物理    ← 物理沒人選

JOIN 比較總覽

INNER JOIN          LEFT JOIN           RIGHT JOIN          FULL JOIN
┌──┬──┐            ┌──┬──┐             ┌──┬──┐            ┌──┬──┐
│██│██│            │██│██│             │██│██│            │██│██│
│  │██│ ← 交集    │██│██│ ← 左全部   │  │██│ ← 右全部  │██│██│ ← 全部
│██│  │            │██│  │             │██│██│            │██│  │
└──┴──┘            └──┴──┘             └──┴──┘            └──┴──┘
JOIN 類型 左表沒配對 右表沒配對
INNER ❌ 不顯示 ❌ 不顯示
LEFT ✅ 顯示(右填 NULL) ❌ 不顯示
RIGHT ❌ 不顯示 ✅ 顯示(左填 NULL)
FULL ✅ 顯示 ✅ 顯示

實用範例

-- 每個客戶的訂單數(包含沒下過單的客戶)
SELECT
    c.Name AS 客戶,
    COUNT(o.Id) AS 訂單數      -- ← 用 COUNT(o.Id) 而不是 COUNT(*)
FROM Customers c                    -- COUNT(o.Id) 遇到 NULL 不計算
LEFT JOIN Orders o ON c.Id = o.CustomerId
GROUP BY c.Name
ORDER BY 訂單數 DESC;

-- 找出沒有訂單的客戶
SELECT c.Name
FROM Customers c
LEFT JOIN Orders o ON c.Id = o.CustomerId
WHERE o.Id IS NULL;

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊