news 2026/10/21 5:12:20

9. 表的内连和外连【由浅入深-MySQL】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
9. 表的内连和外连【由浅入深-MySQL】

文章目录

  • 第一章 连接查询的本质:笛卡尔积与关联条件
  • 第二章 内连接(INNER JOIN):精准匹配的交集
    • 2.1 标准语法结构
    • 2.2 经典案例实战:查询 SMITH 的部门名称
  • 第三章 外连接(OUTER JOIN):主表保全的关联
    • 3.1 左外连接(LEFT JOIN)
    • 3.2 右外连接(RIGHT JOIN)
  • 第四章 外连接实战演练:学生成绩与部门员工案例
    • 4.1 案例一:左连接 —— 展示所有学生及其成绩
    • 4.2 案例二:右连接 —— 展示所有成绩及其对应学生
    • 4.3 综合实战:左右连接互换(列出没有员工的部门)

第一章 连接查询的本质:笛卡尔积与关联条件

在深入探讨内连接和外连接的具体语法之前,我们有必要先理解连接查询的底层数学逻辑。无论是内连接还是外连接,其第一步在数据库内部都是基于两个表做笛卡尔积(Cartesian Product)。

笛卡尔积是指将左表的每一行与右表的每一行进行组合。假设表 A 有 n 行,表 B 有 m 行,那么笛卡尔积的结果将产生 n×m 行临时数据。在实际业务中,这通常是海量且毫无意义的数据。因此,连接查询的核心操作就是在笛卡尔积的基础上,通过关联条件(通常是主外键关系)筛选出符合业务逻辑的有效数据。ON子句和WHERE子句正是我们用来裁剪这张巨大临时表的工具。理解了这一点,你就能明白为什么无条件的多表查询(即不带 WHERE 的逗号连接)会让数据库陷入巨大的性能灾难。

第二章 内连接(INNER JOIN):精准匹配的交集

内连接是日常开发中最常用的连接查询,它在逻辑上可以理解为:仅返回左表和右表中满足连接条件的交集部分。如果某一行在另一张表中没有匹配项,则该行不会出现在最终结果集中。

2.1 标准语法结构

内连接有两种主流的写法,即隐式语法(使用逗号和 WHERE)和显式语法(使用INNER JOIN和ON)。从可读性和现代数据库规范出发,我更推荐使用显式语法,因为它将表与表之间的“连接逻辑”和结果集的“过滤逻辑”分开了。

-- 隐式内连接(传统写法,易读性较差,条件一多容易混乱)SELECT字段列表FROM表1,表2WHERE连接条件AND过滤条件;-- 显式内连接(标准写法,结构清晰)SELECT字段列表FROM表1INNERJOIN表2ON连接条件WHERE过滤条件;

各子句拆解:

  • INNER JOIN:声明连接类型为内连接,INNER关键字通常可以省略,直接写作JOIN。
  • ON子句:专门用于指定两张表之间的关联关系(例如:EMP.deptno = DEPT.deptno)。这是连接查询的灵魂,决定了笛卡尔积的裁剪逻辑。
  • WHERE子句:用于对连接后生成的临时结果集进行业务维度的二次筛选(例如:ename='SMITH')。

常见误区:很多初学者会将关联条件写在WHERE中,虽然结果正确,但在复杂查询中会将连接逻辑与业务逻辑混为一谈,极大地降低了 SQL 的可维护性。

2.2 经典案例实战:查询 SMITH 的部门名称

我们以经典的EMP(员工表)和DEPT(部门表)为例,演示两种语法的实现。假设EMP表中有ename和deptno,DEPT表中有deptno和dname。

方法一:隐式内连接(旧式写法)

SELECTe.ename,d.dnameFROMEMP e,DEPT dWHEREe.deptno=d.deptnoANDe.ename='SMITH';

方法二:显式内连接(标准写法)

SELECTe.ename,d.dnameFROMEMP eINNERJOINDEPT dONe.deptno=d.deptnoWHEREe.ename='SMITH';

执行逻辑推演:
数据库首先计算EMP和DEPT的笛卡尔积。接着,ON e.deptno = d.deptno将结果集限制为只有员工所在部门编号与部门表编号匹配的记录。最后,WHERE e.ename = 'SMITH'在连接后的结果中精准定位到 SMITH 这条记录,并投影出姓名和部门名称。如果 SMITH 的deptno在DEPT表中不存在,那么内连接将返回空结果。

第三章 外连接(OUTER JOIN):主表保全的关联

与内连接只取交集不同,外连接会强制保留某一边(或两边)的所有数据,即使它们在另一张表中没有匹配项。MySQL 支持两种外连接:左外连接(LEFT JOIN)和右外连接(RIGHT JOIN)。

3.1 左外连接(LEFT JOIN)

定义:当进行联合查询时,LEFT JOIN左侧的表(即左表)中的所有记录都会被完整保留到结果集中。如果右表中存在满足ON条件的匹配行,则显示右表数据;如果右表中没有匹配行,则右表所有字段以NULL填充。

语法结构:

SELECT字段列表FROM表1-- 主表(完全显示)LEFTJOIN表2-- 从表(匹配不上则显示 NULL)ON表1.关联字段=表2.关联字段;

适用场景:最常见于“主从数据”查询,例如“查询所有用户及其订单信息,无订单的用户也要显示”。

3.2 右外连接(RIGHT JOIN)

定义:与左外连接恰好相反。RIGHT JOIN右侧的表(即右表)中的所有记录都会被完整保留到结果集中。如果左表没有匹配,则左表字段以NULL填充。

语法结构:

SELECT字段列表FROM表1-- 从表(匹配不上则显示 NULL)RIGHTJOIN表2-- 主表(完全显示)ON表1.关联字段=表2.关联字段;

重要心法:LEFT JOIN和RIGHT JOIN在功能上是完全等价的,本质上互为语法糖。只要将LEFT JOIN中左右两表的顺序互换,同时将LEFT改为RIGHT,查询结果将完全一致。因此,在实际开发中,LEFT JOIN的使用频率远高于RIGHT JOIN,因为人们更习惯将主表写在前面。

第四章 外连接实战演练:学生成绩与部门员工案例

为了深入理解外连接的特性,我们通过两组具体的案例来验证 NULL 填充的细节和左右连接的互换技巧。

4.1 案例一:左连接 —— 展示所有学生及其成绩

准备环境:
首先创建学生表stu和成绩表exam,注意观察两者 ID 的差异(stu表有 ID 4,exam表有 ID 11)。

-- 创建学生表CREATETABLEstu(idINT,nameVARCHAR(30));INSERTINTOstuVALUES(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono');-- 创建成绩表CREATETABLEexam(idINT,gradeINT);INSERTINTOexamVALUES(1,56),(2,76),(11,8);

业务需求:查询所有学生的成绩,如果学生没有成绩,也要显示该学生的个人信息。

分析:需求要求保留所有学生,因此学生表stu必须是主表(左表)。

SELECTs.id,s.name,e.gradeFROMstu sLEFTJOINexam eONs.id=e.id;

结果分析:

  • 学生jack(ID=1)匹配到成绩 56,正常显示。
  • 学生tom(ID=2)匹配到成绩 76,正常显示。
  • 学生kity(ID=3)和nono(ID=4)在exam表中无对应记录,因此e.grade字段返回NULL,但学生个人信息完整显示。

4.2 案例二:右连接 —— 展示所有成绩及其对应学生

业务需求:对stu表和exam表联合查询,把所有的成绩都显示出来,即使这个成绩没有学生与它对应。

分析:需求要求保留所有成绩,因此成绩表exam必须是主表(右表)。

SELECTs.id,s.name,e.idASexam_id,e.gradeFROMstu sRIGHTJOINexam eONs.id=e.id;

结果分析:

  • 成绩 56(ID=1)和 76(ID=2)分别对应jack和tom,正常显示。
  • 成绩 8(ID=11)在stu表中查无此人,因此左表stu的s.id和s.name全部返回NULL,但成绩数据 8 被完整保留。

4.3 综合实战:左右连接互换(列出没有员工的部门)

业务需求:列出部门名称和这些部门的员工信息,同时列出没有员工的部门。

这是一个非常经典的“存在缺失关联”的查询场景。需求要求保留所有部门(即使没有员工),因此部门表DEPT必须是主表。我们利用左右连接等价性,提供两种完全等效的实现方案。

方案一:使用左外连接(DEPT 作为左表)

SELECTd.dname,e.*FROMdept dLEFTJOINemp eONd.deptno=e.deptno;

这张 SQL 以部门为主视角,无论部门下是否有员工,部门名称都会出现。如果该部门下无员工,则员工e.*的所有字段均为NULL。

方案二:使用右外连接(DEPT 作为右表)

SELECTd.dname,e.*FROMemp eRIGHTJOINdept dONd.deptno=e.deptno;

这张 SQL 将DEPT放在了RIGHT JOIN的右侧,将其变为主表。执行结果与方案一完全一致。

开发建议:在实际编码中,你完全可以根据业务主语的表述顺序,灵活选用LEFT或RIGHT。但出于代码的一致性考虑,我强烈建议团队统一规范,只使用LEFT JOIN,将主表固定放在左边,这样可以极大减少因表顺序混乱导致的逻辑误判。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 5:12:06

知识工作插件选型与维护:构建高效个人工作流的实战指南

knowledge-work-plugins 这个名字,第一眼看上去像某个特定工具的代号,我自己最初也以为它是一个仓库或一个软件包。真正让我把它当作一个完整主题来研究的,是知识工作里无处不在的信息断裂:读到一半的文章没地方放,写报…

作者头像 李华
网站建设 2026/10/21 5:10:38

Java图片加密工具:字节流异或位移实现与批量处理改造

简介:这是一份面向Java初学者与信息安全入门者的图片加密实战项目源码,围绕Java IO流与加解密技术,解决图片文件在存储和传输中的安全保护问题。压缩包共5个文件,约514KB,包含java源码与class字节码文件、jpg示例图片以…

作者头像 李华
网站建设 2026/10/21 5:09:42

用Q-learning解随机迷宫:Matlab实现与参数调优全解析

很多初学者接触强化学习,都是从看公式、推导Bellman方程开始的,但翻完整本教材,合上书还是想不清楚这套东西到底怎么跑起来。我建议这类朋友直接上手做一个小项目,比如这个用Q-learning解随机迷宫的问题。项目名字很直白&#xff…

作者头像 李华
网站建设 2026/10/21 5:09:27

Linux服务器性能优化实战:从CPU、内存到磁盘网络的系统调优指南

服务器又卡了,top一看负载飙到几十,CPU使用率却只有不到一半;或者CPU满得冒烟,业务却迟迟没有响应。这种场景,凡是正经做过线上运维的基本都遇到过。Linux服务器性能优化这个主题,说大很大,CPU、…

作者头像 李华
网站建设 2026/10/21 5:09:11

Canvas 2D旋转动画实战:从数学原理到性能优化

1. 从一行标题拆出来的真实需求“可视化2D动画—cavas旋转的圈”,这个标题第一次看到的时候,我脑子里冒出来的画面特别具体:一个用 Canvas 画出来的圆环,可能是一圈点、一圈线段、一圈渐变色块,然后它在那儿匀速转&…

作者头像 李华
网站建设 2026/10/21 5:08:44

知识工作插件体系实战:五类插件选型、配置与工作流串联

1. 先从“知识工作插件”这个标题说起,它到底在解决什么我最初看到"knowledge-work-plugins"这个词组时,第一反应是:这不是某个单一插件,而是一个插件集合,甚至是一整套针对知识工作者打造的效率工具链。所谓…

作者头像 李华