深入理解自连接_图书借阅情况(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博客

相关推荐
斯特凡今天也很帅1 分钟前
clickhouse常用语句汇总——持续更新中
数据库·sql·clickhouse
超级小忍1 小时前
如何配置 MySQL 允许远程连接
数据库·mysql·adb
吹牛不交税2 小时前
sqlsugar WhereIF条件的大于等于和等于查出来的坑
数据库·mysql
hshpy2 小时前
setting up Activiti BPMN Workflow Engine with Spring Boot
数据库·spring boot·后端
文牧之3 小时前
Oracle 审计参数:AUDIT_TRAIL 和 AUDIT_SYS_OPERATIONS
运维·数据库·oracle
篱笆院的狗3 小时前
如何使用 Redis 快速实现布隆过滤器?
数据库·redis·缓存
洛神灬殇4 小时前
【LLM大模型技术专题】「入门到精通系列教程」基于ai-openai-spring-boot-starter集成开发实战指南
网络·数据库·微服务·云原生·架构
小鸡脚来咯4 小时前
redis分片集群架构
数据库·redis·架构
christine-rr5 小时前
征文投稿:如何写一份实用的技术文档?——以软件配置为例
运维·前端·网络·数据库·软件构建
海尔辛5 小时前
SQL 基础入门
数据库·sql