前言
在实际项目开发中,数据通常分散在多张表里。比如用户表、订单表、商品表、权限表,很少单表就能拿到完整结果。多表联查就是把多张表按关联条件合并,一次性查询出所需数据,是后端、测试、数据分析必备技能。
本文使用学生表 (student)、成绩表 (score)、课程表 (course)三张经典案例表,从零讲解多表联查。
一、准备测试表与数据
先建表插数据,可直接复制运行:
-- 学生表 CREATE TABLE student( id INT PRIMARY KEY, name VARCHAR(20), age INT, gender VARCHAR(10) ); -- 成绩表 CREATE TABLE score( id INT PRIMARY KEY, student_id INT, course_id INT, score INT ); -- 课程表 CREATE TABLE course( id INT PRIMARY KEY, name VARCHAR(20) ); -- 插入测试数据 INSERT INTO student VALUES(1,'张三',18,'男'),(2,'李四',19,'男'),(3,'翠花',18,'女'); INSERT INTO course VALUES(101,'语文'),(102,'数学'),(103,'英语'); INSERT INTO score VALUES(1,1,101,88),(2,1,102,95),(3,2,101,76),(4,3,103,92);二、多表联查核心:连接类型一网打尽
1. INNER JOIN(内连接)
作用:只返回两张表匹配成功的数据,没有匹配的不显示。场景:查有成绩的学生 + 课程 + 分数。
SELECT s.name AS 学生姓名, c.name AS 课程名称, sc.score AS 分数 FROM student s INNER JOIN score sc ON s.id = sc.student_id INNER JOIN course c ON sc.course_id = c.id;要点:
- INNER JOIN 可以省略 INNER,直接写 JOIN
- ON 必须写关联条件,不能用错字段
- 结果只显示有成绩的学生
2. LEFT JOIN(左连接)
作用:左表数据全部显示,右表匹配不到显示 NULL。场景:查所有学生,不管有没有成绩。
SELECT s.name AS 学生姓名, c.name AS 课程名称, sc.score AS 分数 FROM student s LEFT JOIN score sc ON s.id = sc.student_id LEFT JOIN course c ON sc.course_id = c.id;使用最多:业务中常用左连接保证主表数据不丢失。
3. RIGHT JOIN(右连接)
作用:右表全部显示,左表匹配不到显示 NULL。场景:查所有课程,不管有没有人选。
SELECT s.name AS 学生姓名, c.name AS 课程名称, sc.score AS 分数 FROM student s RIGHT JOIN score sc ON s.id = sc.student_id RIGHT JOIN course c ON sc.course_id = c.id;4. FULL JOIN(全连接)
作用:左右表数据全部显示,匹配不上补 NULL。MySQL 不支持 FULL JOIN,可用 UNION 模拟:
-- 左连接 + 右连接 去重 = 全连接 SELECT * FROM student s LEFT JOIN score sc ON s.id=sc.student_id UNION SELECT * FROM student s RIGHT JOIN score sc ON s.id=sc.student_id;三、多表联查高频用法
1. 三表联查(最常用)
学生 + 成绩 + 课程,一次性查出完整信息:
SELECT s.id AS 学号, s.name AS 姓名, c.name AS 课程, sc.score AS 成绩 FROM student s JOIN score sc ON s.id=sc.student_id JOIN course c ON sc.course_id=c.id;2. 带条件的多表联查
查询张三的所有成绩:
SELECT c.name AS 课程, sc.score AS 分数 FROM student s LEFT JOIN score sc ON s.id=sc.student_id LEFT JOIN course c ON sc.course_id=c.id WHERE s.name='张三';3. 分组统计 + 多表联查
统计每个学生的平均分:
SELECT s.name, AVG(sc.score) AS 平均分 FROM student s LEFT JOIN score sc ON s.id=sc.student_id GROUP BY s.name;4. 自连接(自己连自己)
适用:层级数据、上下级、评论回复等。
-- 示例:查询同龄学生 SELECT s1.name,s2.name FROM student s1,student s2 WHERE s1.age=s2.age AND s1.id<>s2.id;四、多表联查避坑指南(重点)
- 必须加 ON 条件,否则出现笛卡尔积(数据爆炸)
- 关联字段要加索引,大数据量联查必卡顿
- 少用 FULL JOIN,MySQL 不支持且效率低
- 别名简化表名(s=student、sc=score)可读性更高
- 先过滤再联查,用子查询 / WHERE 减少数据量
五、面试常问:JOIN 总结
- INNER JOIN:取交集
- LEFT JOIN:左表全量 + 右表匹配
- RIGHT JOIN:右表全量 + 左表匹配
- 多表联查:主表放左边,用 LEFT JOIN 最稳
六、总结
- 多表联查核心是找关联字段(外键)
- 日常开发优先用LEFT JOIN
- 三表联查套路:主表 JOIN 附表 1 JOIN 附表 2
- 避坑:无 ON 必错、大数据必加索引
学会多表联查,你就能搞定 90% 的业务查询需求!