想象一下,我們有兩個表格:一個是學生表(記錄了學生的基本信息,比如姓名、年齡),另一個是成績表(記錄了每個學生的考試分數)。如果我們想知道每個學生的具體分數,就需要把這兩個表格的數據“拼”在一起——這就是MySQL的JOIN操作要做的事情!

1. 先了解表結構

假設我們有兩個表:
- 學生表(students):記錄學生的ID和基本信息
| id | name | age |
|-----|------|-----|
| 1 | 小明 | 18 |
| 2 | 小紅 | 19 |
| 3 | 小剛 | 17 |
| 4 | 小強 | 18 |

  • 成績表(scores):記錄學生的分數,通過 student_id 關聯到學生表
    | id | student_id | score |
    |-----|------------|-------|
    | 1 | 1 | 90 | (小明的分數)
    | 2 | 2 | 85 | (小紅的分數)
    | 3 | 3 | 78 | (小剛的分數)
    | 4 | 5 | 95 | (student_id=5的學生分數,但學生表中沒有該學生)

2. 內連接(INNER JOIN)

什麼是內連接?
內連接只返回兩個表中同時存在匹配記錄的行(“兩邊都有的數據才顯示”)。

語法格式

SELECT 列名 FROM 1 INNER JOIN 2 ON 1.關聯字段 = 2.關聯字段;

INNER JOIN 可簡化爲 JOIN,效果相同)

例子
查看所有有分數記錄的學生姓名和分數:

SELECT students.name, scores.score 
FROM students 
INNER JOIN scores 
ON students.id = scores.student_id;

結果集
只包含兩表匹配的記錄(小明、小紅、小剛):
| name | score |
|------|-------|
| 小明 | 90 |
| 小紅 | 85 |
| 小剛 | 78 |

3. 左連接(LEFT JOIN)

什麼是左連接?
左連接返回左表(左邊的表)的所有記錄,右表中沒有匹配的部分用 NULL 填充。

語法格式

SELECT 列名 FROM 1 LEFT JOIN 2 ON 1.關聯字段 = 2.關聯字段;

例子
查看所有學生的姓名和分數(包括沒分數的學生):

SELECT students.name, scores.score 
FROM students 
LEFT JOIN scores 
ON students.id = scores.student_id;

結果集
左表(students)所有學生都保留,右表無匹配則 NULL
| name | score |
|------|-------|
| 小明 | 90 |
| 小紅 | 85 |
| 小剛 | 78 |
| 小強 | NULL |

4. 右連接(RIGHT JOIN)

什麼是右連接?
右連接返回右表(右邊的表)的所有記錄,左表中沒有匹配的部分用 NULL 填充。

語法格式

SELECT 列名 FROM 1 RIGHT JOIN 2 ON 1.關聯字段 = 2.關聯字段;

例子
查看所有分數記錄對應的學生姓名(包括無學生的分數):

SELECT students.name, scores.score 
FROM students 
RIGHT JOIN scores 
ON students.id = scores.student_id;

結果集
右表(scores)所有記錄都保留,左表無匹配則 NULL
| name | score |
|------|-------|
| 小明 | 90 |
| 小紅 | 85 |
| 小剛 | 78 |
| NULL | 95 |

5. 全連接(FULL JOIN)

注意:MySQL本身不支持 FULL JOIN,需用 LEFT JOIN + UNION 模擬。

語法示例

(SELECT students.name, scores.score 
 FROM students 
 LEFT JOIN scores ON students.id = scores.student_id)
UNION
(SELECT students.name, scores.score 
 FROM students 
 RIGHT JOIN scores ON students.id = scores.student_id)
WHERE students.name IS NOT NULL OR scores.score IS NOT NULL;

結果集
包含所有學生和所有分數,無匹配部分用 NULL
| name | score |
|------|-------|
| 小明 | 90 |
| 小紅 | 85 |
| 小剛 | 78 |
| 小強 | NULL |
| NULL | 95 |

6. 常見問題與注意事項

  • 必須寫 ON 子句嗎?
    必須!ON 指定連接條件(如 students.id = scores.student_id),否則 INNER JOIN 會變成笛卡爾積(結果行數=左錶行數×右錶行數,通常錯誤)。

  • 連接條件寫錯怎麼辦?
    ON 條件錯誤(如寫成 students.id = scores.id),關聯失敗,結果可能爲空或數據錯誤。

  • 如何篩選 NULL 值?
    想找“沒分數的學生”:

  SELECT students.name 
  FROM students 
  LEFT JOIN scores ON students.id = scores.student_id 
  WHERE scores.score IS NULL; -- 只顯示小強

總結

  • INNER JOIN:只保留兩表匹配記錄(推薦:需同時存在兩表數據時用)
  • LEFT JOIN:保留左表全部,右表無匹配則 NULL(推薦:需保留主表全部數據時用)
  • RIGHT JOIN:保留右表全部,左表無匹配則 NULL(推薦:需保留從表全部數據時用)

記住“左表保留全部,右表按需匹配”,就能輕鬆掌握JOIN的核心邏輯!

小夜