在真实业务中,我们经常需要跨多张表查询数据。本篇将全面讲解 MySQL 中各种连接查询(JOIN)的使用方式与实战技巧。
一、什么是 JOIN?
JOIN
是 SQL 中用于跨多个表进行数据查询的关键操作。它允许你通过字段之间的关系,把数据「拼接」成一个完整的结果集。
二、JOIN 类型汇总表格
JOIN 类型 | 语法关键字 | 说明 |
---|---|---|
内连接 | INNER JOIN | 只返回两个表中匹配的记录 |
左外连接 | LEFT JOIN | 返回左表所有记录,右表无匹配则为 NULL |
右外连接 | RIGHT JOIN | 返回右表所有记录,左表无匹配则为 NULL |
全外连接(MySQL 不直接支持) | FULL JOIN | 返回两表所有记录,未匹配填 NULL(需模拟) |
自连接 | 自己 JOIN 自己 | 适用于树状结构、自引用表格 |
三、准备数据表结构
-- 学生表
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
class_id INT
);
-- 班级表
CREATE TABLE classes (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
-- 成绩表
CREATE TABLE scores (
id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT,
course_name VARCHAR(50),
score INT
);
四、INNER JOIN(内连接)
-- 查询每位学生的班级名称
SELECT s.name AS student_name, c.name AS class_name
FROM students s
INNER JOIN classes c ON s.class_id = c.id;
✅ 只返回班级信息匹配成功的学生记录。
五、LEFT JOIN(左连接)
-- 查询所有学生以及他们的班级(即使没有班级)
SELECT s.name, c.name AS class_name
FROM students s
LEFT JOIN classes c ON s.class_id = c.id;
✅ 学生存在,班级不存在时,class_name
会为 NULL
。
六、RIGHT JOIN(右连接)
-- 查询所有班级及其对应的学生
SELECT s.name AS student_name, c.name AS class_name
FROM students s
RIGHT JOIN classes c ON s.class_id = c.id;
✅ 即使班级中没有学生,也会被列出。
七、JOIN 多表查询
-- 查询学生、所在班级、及其课程成绩
SELECT s.name AS student_name, c.name AS class_name, sc.course_name, sc.score
FROM students s
JOIN classes c ON s.class_id = c.id
JOIN scores sc ON s.id = sc.student_id;
八、自连接(Self JOIN)
-- 查询每个学生的“同班同学”
SELECT a.name AS student, b.name AS classmate
FROM students a
JOIN students b ON a.class_id = b.class_id AND a.id != b.id;
九、模拟 FULL JOIN(全连接)
MySQL 不支持 FULL JOIN
,可以用 UNION
模拟:
SELECT s.name, c.name AS class_name
FROM students s
LEFT JOIN classes c ON s.class_id = c.id
UNION
SELECT s.name, c.name AS class_name
FROM students s
RIGHT JOIN classes c ON s.class_id = c.id;
十、JOIN 性能优化建议
-
对
JOIN
中参与匹配的字段建索引,提升查询效率; -
限制返回列数,避免
SELECT *
; -
复杂
JOIN
可先视图/子查询; -
使用
EXPLAIN
分析执行计划。
十一、综合练习题
题目: 查询所有班级、对应的学生姓名和各自的选修课程名称与成绩(即使班级或课程为空也要显示)。
🧠 提示:使用 LEFT JOIN
和多表组合,处理 NULL
情况。
总结
-
INNER JOIN
用于严格匹配; -
LEFT/RIGHT JOIN
用于保留一侧所有数据; -
自连接
可处理层级或相似结构; -
多表连接 是复杂查询的核心技能。