想象一下,我们有两个表格:一个是学生表(记录了学生的基本信息,比如姓名、年龄),另一个是成绩表(记录了每个学生的考试分数)。如果我们想知道每个学生的具体分数,就需要把这两个表格的数据“拼”在一起——这就是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的核心逻辑!