深入理解自连接_图书借阅情况(1/2)

经过上一节的"深入理解"内外连接,今天的自连接实际上就是特殊的内连接或外连接。我们会先图示讲解何为自连接,再现学现卖:解决图书借阅情况这个实例。


自连接

概念

自连接(Self-Join)指的是在SQL查询中将同一张表 作为两个不同的实体来使用。而要作为两个不同的实体,在代码里面,表会以两个或多个不同的别名出现,以便在查询中对表自身进行连接

自连接(Self JOIN)指的是++表与其自身进行连接++的操作,在自连接查询中,你可以根据需要使用内连接(INNER JOIN)或外连接(OUTER JOIN),具体取决于你想要获取的数据。

而普通的内外连接是本身两张不同的表,根据匹配结果进行构建结果集。而自连接特殊就特殊在,"自"。

划重点:上面的概念说明,自体现在"表与自身相连",但要应用内外连接这俩种连接方式,往往靠给这张表取几个别名进行连接。

举个例子:

是不是觉得似懂非懂,为什么要进行自身连接呢?那肯定是有这种需求:(下面这个题目取自网络,放心,图肯定是BEAR亲自来)

假设有一个名叫employee的表。需求:找到每个员工及其经理的姓名。

(employee 员工;manager 经理)

我们先抛开什么SQL、什么代码,就人工自查一下:Alice这个员工,她的经理的id号为NULL,说明她还没有经理;Bob的经理的id号为1,我们再去检索每个员工的id,发现id号为1的就是Alice,说明Bob的经理是Alice。同理,Charlie的经理也是Alice。

此处:经理本身也算公司的员工,只是员工之间有上下级关系而已,本质上都是公司的员工。这张表员工id在公司具有唯一性,应为employee表的主键。

经上面简单的人工自查,可以知道,这张表确实可以查出每个人及其对应经理是谁。为了提高效率,亦或者代码实现,我们希望查询出来,直接展示每个员工及其经理的姓名(还未分配经理的员工)。

需求:展示每个员工及其经理的姓名(还未分配经理的员工)。

在需求中,暗示我们不能遗漏每一个员工,不管他/她是否有经理。那么,此处我们使用外连接。外连接,首先得确定主表,从表。

既然需求展示有两部分:员工和经理。我们就需要两张表:e1和e2,从e1中获取员工的姓名,从e2表中获取经理的姓名。保证显示每个员工的姓名,那主表就是e1。

接着就是连接(匹配)条件,要保证形成的结果集中,每个员工横着一排后面跟着的就是对应经理的姓名。

从上图观察,稍微想想,觉得到底哪两个字段能构成匹配条件?🤔

是e1的manager_id和employee_id,您请看,它俩一直在匹配:比如左表和右表的第一行匹配成,结果集在选中字段的时候,就能保证Bob的经理姓名是Alice。

有了主表、连接条件,题目上又说了目的字段,代码就可以上手了。

sql 复制代码
#选中要返回的目的字段值
SELECT e1.name,e2.name
FROM
sql 复制代码
#外连接_自连接
#给表取别名,方便连接
#主表确定
FROM employee e1
LEFT JOIN employee e2
ON
sql 复制代码
#连接条件
ON e1.manager_id = e2.employee_id;

完整代码:

sql 复制代码
SELECT e1.name,e2.name
FROM employee e1
LEFT JOIN employee e2
ON e1.manager_id = e2.employee_id;

#给表取别名_格式
#原表名 别名

好好好,代码说完了,该轮到深入理解环节:上图

上图:细化流程

细节:两张表博主都标的一个颜色,是来源于同一张表的数据。

确定了主表,进行匹配环节:

NULL和任何数据匹配结果往往返回UNKNOWN(不知道),故左表的第一行在e2表中未能找到与之相匹配的employee_id,故匹配不成功。

圈2:轮到e1表的第二行manager_id------ '1' 在e2表的employee_id中寻找匹配,最终e1的'1'与e2的'1'成功匹配。

圈3: 轮到e1表的第三行manager_id------ '1' 在e2表的employee_id中寻找匹配,最终e1的'1'与e2的'1'成功匹配。

圈4:轮到e1表的第四行manager_id------ '2' 在e2表的employee_id中寻找匹配,最终e1的'2'与e2的'2'成功匹配。

圈5: 轮到e1表的第五行manager_id------ '2' 在e2表的employee_id中寻找匹配,最终e1的'2'与e2的'2'成功匹配。

主表匹配完了,不管从表是否全部亦或者没匹配上,都不再匹配了。

下一步:

外连接在构建结果集时,包含主表的所有行,而匹配成功则选中从表的整行;若匹配失败,填充NULL;

接着:数据库发现这个结果集有同名的列,为了避免列名冲突,会进行包含表名或别名的处理。

(手机端看图应该没有PC端体验好,我猜🤔.手机端批阅这篇文的同学,博主感动了🤞,当然PC端也很感动)

有了外连接结果集,接下来就很好办了:

这是使用外连接的自连接。

而使用内连接的自连接也是换汤不换药。

需求:展示已被分配经理的员工及其经理的姓名。

这次,要展示是员工和经理一一对应的数据。意味着,若某个员工没有经理的数据,就不应该进入结果集。两表要同时匹配,即结果为两表的交集------这就是内连接,您说是不是。

我们直接给出代码:连接条件不变

sql 复制代码
SELECT e1.name,e2.name
FROM employee e1
JOIN employee e2
ON e1.manager_id = e2.employee_id;

连接条件不变,是因为思路不变:该怎么找经理就怎么找经理,利用e1的经理的id在e2里面去对应匹配。但展示的细节变了,只显示员工和经理同时存在的记录。

接着,上图,让细节使理解更加到位:

上图:

内连接------无主表,根据匹配条件进行匹配(连接)

NULL与任何值匹配,返回UNKNOWN,故e1的第一行的匹配失败。

圈2:轮到e1表的第二行manager_id------ '1' 在e2表的employee_id中寻找匹配,最终e1的'1'与e2的'1'成功匹配。

圈3: 轮到e1表的第三行manager_id------ '1' 在e2表的employee_id中寻找匹配,最终e1的'1'与e2的'1'成功匹配。

圈4:轮到e1表的第四行manager_id------ '2' 在e2表的employee_id中寻找匹配,最终e1的'2'与e2的'2'成功匹配。

圈5: 轮到e1表的第五行manager_id------ '2' 在e2表的employee_id中寻找匹配,最终e1的'2'与e2的'2'成功匹配。

e1的每行manager_id与e2的每行employee_id都进行了匹配,和外连接匹配时不同,外连接匹配只在意主表是否匹配完毕了。自连接是两表的交集,行数少的表匹配完了,自连接匹配也就完了。

接下来,构建内连接结果集:

同样,构建结果集时,数据库会确保列名唯一,避免列名冲突。

有了内连接结果集,接下来就很好办了:

总结:

自连接(Self JOIN)指的是++表与其自身进行连接++的操作,在自连接查询中,你可以根据需要使用内连接(INNER JOIN)或外连接(OUTER JOIN),具体取决于你想要获取的数据。

自连接应用场景:自连接通常用于查找表中具有某种关系的记录对,比如此处的员工之间的上下级关系。


下一小节,就是现学现卖环节了🤞

如果自连接有些流程不太清楚,那先移步上一节的内外连接,回头来看这篇肯定理解得清清楚楚、明明白白:深入理解:多表查询、多表内外连接查询和子查询-CSDN博客

相关推荐
Mr.1329 分钟前
数据库的三范式是什么?
数据库
Cachel wood36 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Python之栈43 分钟前
【无标题】
数据库·python·mysql
风_流沙1 小时前
java 对ElasticSearch数据库操作封装工具类(对你是否适用嘞)
java·数据库·elasticsearch
亽仒凣凣1 小时前
Windows安装Redis图文教程
数据库·windows·redis
亦世凡华、1 小时前
MySQL--》如何在MySQL中打造高效优化索引
数据库·经验分享·mysql·索引·性能分析
YashanDB1 小时前
【YashanDB知识库】Mybatis-Plus调用YashanDB怎么设置分页
数据库·yashandb·崖山数据库
ProtonBase1 小时前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
云和数据.ChenGuang7 小时前
Django 应用安装脚本 – 如何将应用添加到 INSTALLED_APPS 设置中 原创
数据库·django·sqlite
woshilys7 小时前
sql server 查询对象的修改时间
运维·数据库·sqlserver