MySQL【表的内外连接】

【MySQL 笔记】表的内外连接(JOIN)详解

MySQL 中多表查询最核心的操作就是 JOIN(连接),它决定了如何把两张(或多张)表的数据根据某个条件“拼”在一起。

一、MySQL 支持的 JOIN 类型一览表(2026 年现状)

JOIN 类型写法(常用)保留哪些数据MySQL 原生支持结果行数特征典型业务场景
INNER JOININNER JOIN / JOIN两表都匹配上的行(交集)≤ 最小表行数必须双方都有数据的查询(如订单+用户)
LEFT [OUTER] JOINLEFT JOIN左表全部 + 右表匹配的(右表缺→NULL)= 左表行数查所有学生 + 是否选课(没选的也显示)
RIGHT [OUTER] JOINRIGHT JOIN右表全部 + 左表匹配的(左表缺→NULL)= 右表行数查所有课程 + 选课学生(没人选的也显示)
FULL [OUTER] JOINFULL JOIN / FULL OUTER JOIN两表全部(不匹配处补 NULL)(需模拟)≈ 左表 + 右表 – 交集对比两表差异、合并所有记录
CROSS JOINCROSS JOIN / ,(逗号)笛卡尔积(每行×每行)= 左表行数 × 右表行数生成测试数据、全组合场景
SELF JOIN表自己 JOIN 自己同表不同别名是(语法支持)取决于 ON 条件员工-经理关系、上下级、分类树

二、最核心的四种连接对比(带 Venn 图思维)

想象两张表:学生表(左)选课表(右)

  • INNER JOIN → 两个圆重叠的部分
  • LEFT JOIN → 左圆全部 + 重叠部分
  • RIGHT JOIN → 右圆全部 + 重叠部分
  • FULL JOIN → 两个圆的并集(MySQL 要用 UNION 模拟)

三、经典示例表(建议自己建表跑一遍)

-- 学生表
CREATE TABLE students (
  id   INT PRIMARY KEY,
  name VARCHAR(20)
);

INSERT INTO students VALUES
(1, '小明'), (2, '小红'), (3, '小刚'), (4, '小李'), (5, '小王');

-- 课程表(选课记录)
CREATE TABLE courses (
  sid   INT,          -- 学生ID
  cname VARCHAR(30),
  score TINYINT
);

INSERT INTO courses VALUES
(1, '数学', 95), (1, '英语', 88),
(2, '数学', 76),
(3, '英语', 92), (3, '物理', 85),
(6, '化学', 90);   -- 注意:sid=6 学生不存在

四、各种 JOIN 实战演示

-- 1. INNER JOIN(最常用,只显示有交集的)
SELECT s.name, c.cname, c.score
FROM students s
INNER JOIN courses c ON s.id = c.sid;
-- 结果:小明数学95、小明英语88、小红数学76、小刚英语92、小刚物理85
-- (小李、小王、sid=6 的都不出现)

-- 2. LEFT JOIN(保留左表全部)
SELECT s.name, c.cname, c.score
FROM students s
LEFT JOIN courses c ON s.id = c.sid;
-- 结果:上面5行 + 小李 NULL NULL + 小王 NULL NULL

-- 3. RIGHT JOIN(保留右表全部)
SELECT s.name, c.cname, c.score
FROM students s
RIGHT JOIN courses c ON s.id = c.sid;
-- 结果:上面5行 + NULL 化学 90  (sid=6 没有对应学生)

-- 4. MySQL 模拟 FULL JOIN(最常用写法)
(SELECT s.name, c.cname, c.score
 FROM students s
 LEFT JOIN courses c ON s.id = c.sid)
UNION
(SELECT s.name, c.cname, c.score
 FROM students s
 RIGHT JOIN courses c ON s.id = c.sid
 WHERE s.id IS NULL);   -- 避免重复

-- 结果:左表全部 + 右表独有的(sid=6 那行)

-- 5. CROSS JOIN(笛卡尔积,慎用!)
SELECT s.name, c.cname
FROM students s
CROSS JOIN courses c;
-- 结果:5学生 × 6条选课记录 = 30行(爆炸式增长)

-- 6. SELF JOIN 示例(员工找经理)
-- 假设 employees 表有 id, name, manager_id
SELECT e.name AS 员工, m.name AS 经理
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;

五、高频使用场景总结(面试+实战)

场景推荐 JOIN 类型为什么
订单 + 用户信息(必须有用户)INNER JOIN没用户的订单通常是脏数据
所有商品 + 销量(没卖出的显示0)LEFT JOIN商品表为主,销量表可能缺记录
所有课程 + 报名学生数LEFT JOIN + GROUP BY课程表为主,没人报名的也要显示
找出两表差异记录FULL JOIN(模拟)或 LEFT+RIGHT+UNION常用于数据对账、同步检查
生成测试数据、全组合CROSS JOIN很少用于生产,常见于 mock 数据
上下级、分类父子关系SELF JOIN表自己连自己

六、写 JOIN 的小技巧 & 注意点

  1. 永远写 ON 条件(别用 WHERE 写连接条件,容易逻辑混乱)
  2. 小表驱动大表:把数据量小的表放左边(尤其是 LEFT JOIN)
  3. 索引:JOIN 字段必须有索引(尤其是 WHERE / ON / GROUP BY 涉及的列)
  4. 用别名:表名长时必须起别名(s、c、u、o 常用)
  5. NULL 判断:LEFT/RIGHT 后常用 WHERE xx IS NULL 找“只有左/右表有的”
  6. FULL JOIN 替代方案:LEFT JOIN + UNION + RIGHT JOIN(WHERE 左表 IS NULL)

下一期预告建议:MySQL 多表 JOIN 性能优化 + EXPLAIN 分析 + 索引使用技巧

有 JOIN 写法特别迷惑的业务场景,欢迎留言,我们一起画图分析~
祝大家 JOIN 写得又快又准!🚀

文章已创建 5186

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部