深入剖析多个表left join on的执行步骤原理:实战案例解析与原理探讨

Left join on系列文章
测试一下你真的理解数据库左连接了吗?
SQL连接与筛选:解析left join on和where的区别及典型案例分析
深入剖析多个表left join on的执行步骤原理:实战案例解析与原理探讨

文章导图

在这里插入图片描述

前言

日常工作中写SQL,我们会经常left join一堆表,我最多见过的有20多张的。。。(在一家外企,然后还用了一堆存储过程有几千行的,吐了。。。)那么对于left join on和前面表关联条件的时候,有的时候是紧挨着的表,有的是隔开的,有啥区别呢?具体看看这个

SELECT *
FROM a
LEFT JOIN b ON a.aid = b.aid
LEFT JOIN c ON b.bid = c.bid
LEFT JOIN d ON c.cid = d.cid
LEFT JOIN e ON d.did = e.did
LEFT JOIN f ON e.eid = f.eid

上面这种我们更好理解一点,就是一步步的去关联join on紧挨着的前面表,我们来看下面这种有啥区别?

SELECT *
FROM a
LEFT JOIN b ON a.aid = b.aid
LEFT JOIN c ON a.cid = c.cid
LEFT JOIN d ON a.did = d.did
LEFT JOIN e ON d.eid = e.eid
LEFT JOIN f ON c.fid = f.fid

这种关联关系是不是会看的眼花缭乱,一开始a和b是正常通过a.aid=b.aid,一下子join c的时候又是a.cid=c.cid,join f的时候条件又是c.fid=f.fid…

现在我们来简化一下上面的SQL,a 表主键是aid,b表是bid,c表是cid,两个语句有什么区别?如何理解?

select * from  a left join b on a.aid=b.aid  left join c on b.bid=c.bid

select * from  a left join b on a.aid=b.aid  left join c on a.aid=c.aid

这就是我们本篇文章的重点,相信理解了这两种,上面那种花里胡哨的各种left join 关联关系我们也能够手到擒来!

初始化数据-建表

这里我们把表的结构建的尽量足够简单,主要是为了理解我们的left join的整个过程

create table a
(
    aid    int          not null
        primary key,
    a_name varchar(100) null
);

create table b
(
    bid int not null
        primary key,
    aid int null,
    b_name varchar(100) null
   
);

create table c
(
    cid    int          not null
        primary key,
    bid    int          null,
    aid    int          null,
    c_name varchar(100) null
);

插入一些初始化数据

INSERT INTO a (aid, a_name) VALUES (1, 'a1');
INSERT INTO a (aid, a_name) VALUES (2, 'a2');
INSERT INTO a (aid, a_name) VALUES (3, 'a3');

INSERT INTO b (bid, aid, b_name) VALUES (1, 1, 'b1');
INSERT INTO b (bid, aid, b_name) VALUES (2, 2, 'b2');

INSERT INTO c (cid, bid, aid, c_name) VALUES (1, 1, 1, 'c1');
INSERT INTO c (cid, bid, aid, c_name) VALUES (2, 2, 2, 'c2');

a表数据

aida_name
1a1
2a2
3a3

b表数据

bidaidb_name
11b1
22b2

c表数据

cidbidaidc_name
111c1
222c2

两个表left jion

如果只是2个表连接,我在之前的文章已经分析的很清楚了SQL连接与筛选:解析left join on和where的区别及典型案例分析

SELECT * FROM a LEFT JOIN b ON a.aid = b.aid

执行结果应该是下面这个样子,这里就不过多解释,不理解可以看我之前的文章

aida_namebidaidb_name
1a111b1
2a222b2
3a3

那么现在再多left jion 一张表(或者多张表),原理是类似的,但是会分为2种前情况,

  • 一种是left join紧挨着的这张表,也就是在原有2表关联的基础上加上left jion on c.bid=b.bid,但是它的left join是紧挨着的b表
  • 一种是left join非紧挨着的表,也就是在原有2表关联的基础上加上left jion on c.aid=a.aid,但是它的left join是非紧挨着的a表

接下来我们分别解析这两种情况

多表-left jion on c.bid=b.bid分析|

这种查询适用于你想要根据表b的某些条件或关系来过滤或连接表c的情况。这种情况下,表c与表a的关联是间接的,通过表b实现。

SQL语句如下:

SELECT *
FROM a
         LEFT JOIN b ON a.aid = b.aid
         LEFT JOIN c ON b.bid = c.bid

执行步骤和结果

  1. 第一步: 执行 a LEFT JOIN b ON a.aid = b.aid

    • 这会将表 a 中的每一行与表 b 中的行进行连接,条件是 a.aid = b.aid
    • 如果表 b 中没有对应的 aid,则结果中 b 的列将填充 NULL
  2. 第二步: 对第一步的结果再进行 LEFT JOIN c ON b.bid = c.bid

    • 这会将第一步的结果与表 c 中的行进行连接,条件是 b.bid = c.bid
    • 如果表 c 中没有对应的 bid,则结果中 c 的列将填充 NULL

image-20240713122236470

理解

  • 如果表 b 中没有匹配 a.aid 的行,那么 bc 的所有列都会是 NULL
  • 即使 ab 有匹配,但 b.bid 在表 c 中没有匹配的行,c 的列也会是 NULL

变形-修改c表数据

变形1

第一种情况,我们来修改C表数据,将bid由原来的2,修改成了3

cidbidaidc_name
111c1
23(由2修改成了3)3c2

而原来的b表是没有bid=3的数据,那么继续执行原来的SQL,结果如下

  • c表通过bid与b表关联,对于b表的bid=1能找到,所以正常显示了c表的数据
  • 对于b表的bid=2,在c表找不到关联数据,就显示NULL

image-20240713121812692

变形2

第二种情况,我们来修改C表数据,将bid由原来的2,修改成了1

cidbidaidc_name
111c1
21(由2修改成了1)3c2

对于b表的bid=1,会再c表中找到2条数据,所以b表bid=1数据显示2遍一样的,然后再对应上c表的2条不一样的数据

image-20240713124021452

总结

以上这种left jion on c.bid=b.bid再多关联一张表c,分析起来和2张表关联a和b是一样的,我们这里只是多举几种例子让大家更深刻理解一下

接下来的left jion on c.aid=a.aid才是我们的重点,也就是关联的表是前面的表,也就是不是挨着的。

多表-left jion on c.aid=a.aid分析

这种查询适用于当你直接在表a和表c之间建立关系时。这里表b的加入不影响表a与表c之间的连接。

SELECT *
FROM a
         LEFT JOIN b ON a.aid = b.aid
         LEFT JOIN c ON a.aid = c.aid;

执行步骤和结果

  1. 第一步: 执行 a LEFT JOIN b ON a.aid = b.aid

    • 这部分和第一个查询是相同的,将表 a 和表 b 进行连接,条件是 a.aid = b.aid
    • 如果没有匹配的 aid,则 b 的列将填充 NULL
  2. 第二步: 对第一步的结果再进行 LEFT JOIN c ON a.aid = c.aid

    • 这会将第一步的结果与表 c 中的行进行连接,条件是 a.aid = c.aid
    • 如果表 c 中没有对应的 aid,则结果中 c 的列将填充 NULL

image-20240713130424223

结果分析:

  • 忽略b表数据,只看当前关联的a和c表即可
  • 可以发现a表的aid=1,2都能在c表找到数据,所以c表数据也是全的

理解

简单来说,我们其实在每一次关联的时候,只看关联的两个表的数据,中间的别的表不管有多少个,都不用管,即可

  • 不论表 b 是否有匹配的行,ac 都是直接连接在一起的,条件是 a.aid = c.aid
  • 如果 a.aid 在表 c 中没有匹配的行,c 的列将会是 NULL,无论 b 是否有匹配的 bid

变形-修改c表数据

变形1

第一种情况,我们同样来修改C表数据,将aid由原来的2,修改成了4

cidbidaidc_name
111c1
224(由2修改成了4)c2

而原来的a表是没有aid=4的数据,那么继续执行原来的SQL,结果如下

image-20240713131833810

  • c表通过aid与a表关联,对于a表的aid=1能找到,所以正常显示了c表的数据
  • 对于c表的aid=4,在a表找不到关联数据,就显示NULL

变形2

第二种情况,我们来修改c表数据,将aid由原来的2,修改成了1

cidbidaidc_name
111c1
221(由2修改成了1)c2

对于a表的aid=1,会再c表中找到2条数据,所以a表aid=1数据显示2遍一样的,然后再对应上c表的2条不一样的数据

image-20240713132249605

解答开头

那么我们再来看下最开头的SQL

SELECT *
FROM a
LEFT JOIN b ON a.aid = b.aid
LEFT JOIN c ON a.cid = c.cid
LEFT JOIN d ON a.did = d.did
LEFT JOIN e ON d.eid = e.eid
LEFT JOIN f ON c.fid = f.fid

让我们逐步解析这个查询:

  1. 从表 a 开始

    SELECT *
    FROM a
    
  2. 左连接表 b

    LEFT JOIN b ON a.aid = b.aid
    

    这意味着表 a 中的每一行都会与表 baid 相等的行进行匹配。如果表 b 中没有匹配的行,结果中对应表 b 的列将包含 NULL 值。

  3. 左连接表 c

    LEFT JOIN c ON a.cid = c.cid
    

    类似地,表 a 中的每一行会与表 ccid 相等的行进行匹配。

  4. 左连接表 d

    LEFT JOIN d ON a.did = d.did
    

    a 中的每一行会与表 ddid 相等的行进行匹配。

  5. 左连接表 e

    LEFT JOIN e ON d.eid = e.eid
    

    这里需要注意的是,表 e 是通过表 d 连接的,而不是直接通过表 a。这意味着表 d 中的每一行会与表 eeid 相等的行进行匹配。

  6. 左连接表 f

    LEFT JOIN f ON c.fid = f.fid
    

    类似地,表 f 是通过表 c 连接的,而不是直接通过表 a。表 c 中的每一行会与表 ffid 相等的行进行匹配。

总结一下,这个查询的结果将包含表 a 中的所有行,以及与表 bcdef 中匹配的行。如果某个表中没有匹配的行,结果中对应该表的列将包含 NULL 值。

总结

这两条SQL其实理解了以后,我们会发现其他类似的SQL执行步骤和原理都是一样的

select * from a left join b on a.aid=b.aid left join c on b.bid=c.bid

select * from a left join b on a.aid=b.aid left join c on a.aid=c.aid

其实大的前提就是我们要记住:

  1. 我们在每一次关联的时候,只看当前执行到的关联的两个表的数据,中间的别的表不管有多少个,都不用管即可
  2. 比如当前执行left join on a.aid=b.bid,那么我们主要关注a表和b表之间的数据
  3. 然后继续执行到left join on a.aid=b.bid left join a.aid=c.aid时,就是在前面数据的基础上 (也就是执行完SELECT * FROM a LEFT JOIN b ON a.aid = b.aid,然后把这个数据当做一个整体) ,再去看我们关联的表即可
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Apple_Web

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值