深入理解自连接_图书借阅情况(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。
有了主表、连接条件,题目上又说了目的字段,代码就可以上手了。
#选中要返回的目的字段值
SELECT e1.name,e2.name
FROM
#外连接_自连接
#给表取别名,方便连接
#主表确定
FROM employee e1
LEFT JOIN employee e2
ON
#连接条件
ON e1.manager_id = e2.employee_id;
完整代码:
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端也很感动)
有了外连接结果集,接下来就很好办了:
这是使用外连接的自连接。
而使用内连接的自连接也是换汤不换药。
需求:展示已被分配经理的员工及其经理的姓名。
这次,要展示是员工和经理一一对应的数据。意味着,若某个员工没有经理的数据,就不应该进入结果集。两表要同时匹配,即结果为两表的交集——这就是内连接,您说是不是。
我们直接给出代码:连接条件不变
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博客