SQL 多表联查从入门到精通,INNER/LEFT/RIGHT/FULL JOIN 一篇吃透

前言

在实际项目开发中,数据通常分散在多张表里。比如用户表、订单表、商品表、权限表,很少单表就能拿到完整结果。多表联查就是把多张表按关联条件合并,一次性查询出所需数据,是后端、测试、数据分析必备技能。

本文使用学生表 (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;

四、多表联查避坑指南(重点)

  1. 必须加 ON 条件,否则出现笛卡尔积(数据爆炸)
  2. 关联字段要加索引,大数据量联查必卡顿
  3. 少用 FULL JOIN,MySQL 不支持且效率低
  4. 别名简化表名(s=student、sc=score)可读性更高
  5. 先过滤再联查,用子查询 / WHERE 减少数据量

五、面试常问:JOIN 总结

  • INNER JOIN:取交集
  • LEFT JOIN:左表全量 + 右表匹配
  • RIGHT JOIN:右表全量 + 左表匹配
  • 多表联查:主表放左边,用 LEFT JOIN 最稳

六、总结

  1. 多表联查核心是找关联字段(外键)
  2. 日常开发优先用 LEFT JOIN
  3. 三表联查套路:主表 JOIN 附表 1 JOIN 附表 2
  4. 避坑:无 ON 必错、大数据必加索引

学会多表联查,你就能搞定 90% 的业务查询需求!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值