想象一下,我們有兩個表格:一個是學生表(記錄了學生的基本信息,比如姓名、年齡),另一個是成績表(記錄了每個學生的考試分數)。如果我們想知道每個學生的具體分數,就需要把這兩個表格的數據“拼”在一起——這就是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的核心邏輯!