MySQL内、外连接知识点汇总

以下是 SQL 外连接的完整讲解,包含INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN 以及内、外连接的核心概念,全部用表格举例说明。


一、内连接 vs 外连接核心区别

表格

复制

对比项 内连接 (INNER JOIN) 外连接 (LEFT/RIGHT/FULL JOIN)
匹配规则 只返回两表匹配的行 返回匹配行 + 未匹配行(补 NULL)
结果集大小 ≤ 两表匹配行数 ≥ 内连接结果(可能更大)
未匹配数据处理 丢弃 保留,缺失侧补 NULL
使用场景 只关心两表都有的数据 需要保留某表全部数据
图示 两圆交集 左圆 / 右圆 / 两圆全部

二、示例数据表

employees 员工表(左表)

表格

emp_id emp_name dept_id
1 张三 10
2 李四 20
3 王五 10
4 赵六 NULL
5 孙七 50

departments 部门表(右表)

表格

dept_id dept_name
10 技术部
20 销售部
30 财务部

三、INNER JOIN(内连接)回顾

sql

复制代码
SELECT e.emp_name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.dept_id;

结果:

表格

emp_name dept_name 说明
张三 技术部 匹配
王五 技术部 匹配
李四 销售部 匹配

未匹配的行被丢弃:赵六(dept_id=NULL)、孙七(dept_id=50 无对应部门)、财务部(无员工)


四、LEFT JOIN(左外连接)

语法

sql

复制代码
SELECT e.emp_name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.dept_id;

规则

表格

规则 说明
保留左表全部行 employees 表所有 5 条记录都出现
右表匹配不上 补 NULL
右表有多条匹配 左表行重复显示

结果

表格

emp_name dept_name 来源分析
张三 技术部 左表 + 右表匹配
王五 技术部 左表 + 右表匹配
李四 销售部 左表 + 右表匹配
赵六 NULL 左表有,右表无匹配(dept_id=NULL)
孙七 NULL 左表有,右表无匹配(dept_id=50 不存在)

使用场景

表格

场景 示例
查询所有员工,不管有没有部门 SELECT * FROM employees LEFT JOIN departments
查询未分配部门的员工 WHERE d.dept_id IS NULL
查询所有订单及客户信息(含未下单客户) 客户表 LEFT JOIN 订单表

五、RIGHT JOIN(右外连接)

语法

sql

复制代码
SELECT e.emp_name, d.dept_name
FROM employees e
RIGHT JOIN departments d ON e.dept_id = d.dept_id;

规则

表格

规则 说明
保留右表全部行 departments 表所有 3 条记录都出现
左表匹配不上 补 NULL

结果

表格

emp_name dept_name 来源分析
张三 技术部 右表 + 左表匹配
王五 技术部 右表 + 左表匹配
李四 销售部 右表 + 左表匹配
NULL 财务部 右表有,左表无匹配(无员工)

使用场景

表格

场景 示例
查询所有部门,不管有没有员工 RIGHT JOINLEFT JOIN 换表顺序
查询没有员工的部门 WHERE e.emp_id IS NULL

注意:RIGHT JOIN 实际开发中较少使用,通常用 LEFT JOIN + 换表顺序替代,更易读。


六、FULL JOIN(全外连接)

语法

sql

复制代码
SELECT e.emp_name, d.dept_name
FROM employees e
FULL JOIN departments d ON e.dept_id = d.dept_id;

规则

表格

规则 说明
保留两表全部行 左表 + 右表所有记录都出现
匹配不上的 各自补 NULL
结果集 LEFT JOIN 结果 ∪ RIGHT JOIN 结果

结果

表格

emp_name dept_name 来源分析
张三 技术部 两表匹配
王五 技术部 两表匹配
李四 销售部 两表匹配
赵六 NULL 仅左表有
孙七 NULL 仅左表有
NULL 财务部 仅右表有

MySQL 特殊说明

表格

数据库 FULL JOIN 支持
PostgreSQL ✅ 原生支持
SQL Server ✅ 原生支持
Oracle ✅ 原生支持
MySQL 不支持

MySQL 实现 FULL JOIN 的替代方案:

sql

复制代码
-- UNION 合并 LEFT + RIGHT
SELECT e.emp_name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.dept_id

UNION

SELECT e.emp_name, d.dept_name
FROM employees e
RIGHT JOIN departments d ON e.dept_id = d.dept_id;

七、四种连接对比总表

表格

连接类型 保留左表全部 保留右表全部 结果行数 图示
INNER JOIN 3行(仅匹配) 两圆交集
LEFT JOIN 5行(左表全部) 左圆全部
RIGHT JOIN 4行(右表全部) 右圆全部
FULL JOIN 6行(两表全部) 两圆全部

八、未匹配数据筛选(经典场景)

场景1:查询没有部门的员工

sql

复制代码
SELECT e.emp_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.dept_id
WHERE d.dept_id IS NULL;

结果:

表格

emp_name
赵六
孙七

场景2:查询没有员工的部门

sql

复制代码
SELECT d.dept_name
FROM employees e
RIGHT JOIN departments d ON e.dept_id = d.dept_id
WHERE e.emp_id IS NULL;

-- 或更常见的写法(LEFT JOIN 换顺序)
SELECT d.dept_name
FROM departments d
LEFT JOIN employees e ON d.dept_id = e.dept_id
WHERE e.emp_id IS NULL;

结果:

表格

dept_name
财务部

场景3:查询两表完全无关联的数据(MySQL 模拟 FULL JOIN 取差集)

sql

复制代码
-- 没有部门的员工 + 没有员工的部门
SELECT e.emp_name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.dept_id
WHERE d.dept_id IS NULL

UNION

SELECT e.emp_name, d.dept_name
FROM departments d
LEFT JOIN employees e ON d.dept_id = e.dept_id
WHERE e.emp_id IS NULL;

结果:

表格

emp_name dept_name
赵六 NULL
孙七 NULL
NULL 财务部

九、实际开发选择指南

表格

需求 应使用的连接
只查两表都有的数据 INNER JOIN
查 A 表全部 + B 表匹配数据 A LEFT JOIN B
查 B 表全部 + A 表匹配数据 B LEFT JOIN A(推荐)或 A RIGHT JOIN B
查 A 表独有的数据 A LEFT JOIN B WHERE B.key IS NULL
查 B 表独有的数据 B LEFT JOIN A WHERE A.key IS NULL
查两表全部(含未匹配) FULL JOIN(MySQL 用 UNION 模拟)
查两表各自独有的数据 (A LEFT JOIN B WHERE B IS NULL) UNION (B LEFT JOIN A WHERE A IS NULL)

十、一句话总结

表格

连接 口诀
INNER JOIN 两表都有才保留
LEFT JOIN 左表全留,右表没有补 NULL
RIGHT JOIN 右表全留,左表没有补 NULL
FULL JOIN 两表全留,各自没有补 NULL
相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
小羊没烦恼!2 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
俊昭喜喜里2 天前
java中的继承和多态的区别
java
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
譕痕2 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖2 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商