别再left join上面栽跟头,你需要知道的left join中 on 等值条件的作用

话说我就在left join这个问题上吃了亏,因为之前就知道有这么个问题的,可以没有深究下去,终究在某个场合吃了亏

让我想起来一句话:出来混,总是要还的

对于有疑问的地方,要彻底弄清楚,弄明白,确保以后不会因为此类造成困扰

create table class
(
	class_id varchar(10),
	class_name varchar(50)
)

insert into class values (1,'语文');
insert into class values (2,'数学');
insert into class values (3,'英语');


create table score
(
	class_id varchar(10),
	Student_id varchar(10),
	Score int
)

insert into score values (1,'A001',90);
insert into score values (2,'A001',95);
insert into score values (1,'A002',80);
insert into score values (2,'A002',85);
insert into score values (1,'B001',88);


select * from class
select * from score


--一个课程表,一个成绩表
--表数据分布是
--成绩表:有三个学生A,B,C,
--A,B都有语文和数学成绩,
--C只有语文成绩;
--A,B,C都没有英语成绩,
--课程表,有语文,数学,英语三门课程,没有“体育”这门课程



--如果你对left join足够熟悉的话,先不要看结果,是否可以直接说出下面查询的结果

select * from class A left join score B on A.class_id=B.class_id and A.class_name='语文'
select * from class A left join score B on A.class_id=B.class_id and A.class_name='数学'
select * from class A left join score B on A.class_id=B.class_id and A.class_name='英语'
select * from class A left join score B on A.class_id=B.class_id and A.class_name='体育'



select * from class A left join score B on A.class_id=B.class_id 
where A.class_name='语文'

select * from class A left join score B on A.class_id=B.class_id 
where A.class_name='数学'

select * from class A left join score B on A.class_id=B.class_id 
where A.class_name='英语'

select * from class A left join score B on A.class_id=B.class_id 
where A.class_name='体育'



--其实结果我不想贴了,以后再整理,如果结果跟你预期的不一样,
--或者你对查询结果感到疑惑,下面就是对上面结果的解释


/***************************************过滤条件在on中时********************************/

--不管on中的条件如何写,左连接首先要得到左边的所有的行
--对于右边的表,如果满足连接条件,则输出值,如果不满足条件,则返回null
--也就是说,on中的过滤条件(比如 on leftTable.id=rightTable.id  and leftTable.colName='***'),
--是作为左外连接的连接条件,而不是过滤条件
--左边表的数据是要全部输出的,做联接的时候,
--抽取符合(leftTable.colName='***')条件的的左边的数据行,跟右边的表做连接,输出结果
--不符合(leftTable.colName='***')条件的数据行,输出左边表,右边表为null值,输出结果
比如这个sql:
select * from class A left join score B on A.class_id=B.class_id and A.class_name='英语'

查询过程是这样的:
找出A表的第一条数据,判断是否符合class_name='英语'
如果符合,则跟右表做,输出A表+B表的行(当然存在B表中可能没有相关ID的英语成绩,那么B表也可以输出null)
如果不符,直接输出A表中的行,B表中的行直接为null

从这个过程可以看出,on中的等值条件只是影响left join产生结果集的过程,并不参与数据的过滤
A表总是将其所有的值输出的(不管过滤条件是啥,不管B表是否存在相关信息)





/************************************过滤条件在where中时********************************/

--但是过滤条件写在where中(on leftTable.id=rightTable.id where  leftTable.colName='***')时,
--是作为对左边表的“过滤条件”,就意味着先根据where(where  leftTable.colName='***')条件过滤左边的表
--然后将过滤后的结果跟右边的表做左联接连接







  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值