【MySQL】表的内连接和外连接

【MySQL】表的内连接外连接详解(带图解思路 + 代码示例 + 面试常考点)

在MySQL中,JOIN 是多表查询的核心操作,主要分为内连接(INNER JOIN)外连接(OUTER JOIN) 两大类。外连接又细分为 LEFT、RIGHT、FULL 三种。

一句话记住本质区别:

  • 内连接:只取两个表都匹配上的记录(交集)
  • 外连接:至少保留其中一张表的所有记录,匹配不上的用 NULL 填充

1. 经典 Venn 图理解(强烈建议脑补或画出来)

想象两个圆圈 A 表(左)和 B 表(右):

  • INNER JOIN:只取 A ∩ B(两个圆重叠的部分)
  • LEFT JOIN:取 A 全部 + A ∩ B(左圆全要,重叠部分也取,右圆只取重叠)
  • RIGHT JOIN:取 B 全部 + A ∩ B(右圆全要)
  • FULL OUTER JOIN:取 A ∪ B(两个圆全部,包括不重叠的部分)

MySQL 不支持 直接的 FULL OUTER JOIN,但可以用 LEFT + RIGHT + UNION 模拟。

2. 准备示例表(经典学生-课程表)

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

INSERT INTO students VALUES
(1, '张三'),
(2, '李四'),
(3, '王五'),     -- 没选课
(4, '赵六');     -- 没选课

-- 选课表(右表)
CREATE TABLE courses (
    student_id INT,
    course_name VARCHAR(20)
);

INSERT INTO courses VALUES
(1, '数学'),
(1, '英语'),
(2, '物理'),
(5, '化学');     -- student_id=5 不存在于学生表

3. 各种 JOIN 的 SQL + 结果解释

(1) INNER JOIN(内连接,默认就是这个)

SELECT s.name, c.course_name
FROM students s
INNER JOIN courses c
ON s.id = c.student_id;

结果(只返回匹配的):

namecourse_name
张三数学
张三英语
李四物理

只显示有选课的学生,王五、赵六没出现;5号课程也没出现。

等价写法(老式隐式内连接):

SELECT s.name, c.course_name
FROM students s, courses c
WHERE s.id = c.student_id;

(2) LEFT JOIN / LEFT OUTER JOIN(左外连接,最常用)

SELECT s.name, c.course_name
FROM students s
LEFT JOIN courses c
ON s.id = c.student_id;

结果

namecourse_name
张三数学
张三英语
李四物理
王五NULL
赵六NULL

左表(students)全部保留,没匹配的课程显示 NULL。

面试常问:LEFT JOIN 后 WHERE 放 ON 还是 WHERE 区别很大!

  • ON 条件:过滤连接前的匹配
  • WHERE 条件:过滤连接后的结果(可能把 LEFT 的 NULL 行干掉)

错误示范(想保留左表全部却加了 WHERE c.course_name IS NOT NULL → 变内连接了)。

(3) RIGHT JOIN / RIGHT OUTER JOIN(右外连接)

SELECT s.name, c.course_name
FROM students s
RIGHT JOIN courses c
ON s.id = c.student_id;

结果

namecourse_name
张三数学
张三英语
李四物理
NULL化学

右表(courses)全部保留,没匹配的学生显示 NULL。

注意:LEFT 和 RIGHT 可以互相转换(把表顺序换一下 + 改 JOIN 类型),实际开发中 LEFT JOIN 占 90%,RIGHT 很少用。

(4) FULL OUTER JOIN(全外连接)—— MySQL 不原生支持

模拟写法(LEFT + RIGHT + 去重):

SELECT s.name, c.course_name
FROM students s
LEFT JOIN courses c ON s.id = c.student_id

UNION

SELECT s.name, c.course_name
FROM students s
RIGHT JOIN courses c ON s.id = c.student_id
WHERE s.id IS NULL;   -- 避免重复

结果(并集):

namecourse_name
张三数学
张三英语
李四物理
王五NULL
赵六NULL
NULL化学

4. 快速对比表(面试/刷题必背)

JOIN 类型返回内容保留哪张表全部记录没匹配的字段MySQL 支持使用场景
INNER JOIN只匹配上的(A ∩ B)无(不出现)必须双方都有数据
LEFT JOIN左表全部 + 匹配的左表右表字段=NULL找左表所有 + 右表补充
RIGHT JOIN右表全部 + 匹配的右表左表字段=NULL找右表所有 + 左表补充(少用)
FULL OUTER JOIN左右表全部(A ∪ B)两表NULL填充需要完整并集(用 UNION 模拟)

5. 面试/笔试高频考点总结

  1. INNER JOIN vs WHERE 写法区别(性能、语义)
  2. LEFT JOIN + WHERE 条件放错位置导致结果变内连接
  3. 如何模拟 FULL JOIN(UNION + WHERE IS NULL 去重)
  4. 多表 JOIN 时顺序影响(尤其是 LEFT + INNER 混用)
  5. ON vs USING(USING 只适用于同名字段)
  6. 自连接(SELF JOIN)、交叉连接(CROSS JOIN)也常一起问

一句话口诀
内连接求交集,外连接求并集(LEFT 保左、RIGHT 保右、FULL 保双),没匹配的就 NULL 补位。

你现在是想看具体业务场景示例(比如订单+用户、员工+部门),还是想练几道 JOIN 题型?
或者有某个 JOIN 的 WHERE/ON 细节困惑?告诉我,继续深挖!

文章已创建 4799

发表回复

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

相关文章

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

返回顶部