SQL中JOIN時(shí)條件放在Where和On的區(qū)別
背景
SQL中JOIN子句是用于把來自兩個(gè)或多個(gè)表的數(shù)據(jù)連接起來,在這個(gè)過程中可能會(huì)添加一些過濾條件。昨天有小伙伴問,如下圖的這兩種SQL寫法查詢結(jié)果是否會(huì)一樣?(好像這是某一年阿里的面試題)

這個(gè)問題提出來以后,多數(shù)小伙伴的回答是:查詢結(jié)果應(yīng)該是一樣的吧,只是查詢效率不一樣。我當(dāng)時(shí)的回答是,在Inner Join時(shí)這兩種情況返回的結(jié)果是一樣的,在Left、Right等情況時(shí)結(jié)果不一樣。
案例
1、創(chuàng)建測試數(shù)據(jù)庫和表并且插入用戶測試的數(shù)據(jù)。
--?創(chuàng)建數(shù)據(jù)庫
CREATE?DATABASE?ods_study_1;
USE?ods_study_1;
--?創(chuàng)建表
CREATE?TABLE?ods_study_1.ods_study_join_a
(
study_id_a?int
);
CREATE?TABLE?ods_study_1.ods_study_join_b
(
study_id_b?int,
study_channel?varchar(255)
);
--?插入數(shù)據(jù)
INSERT?INTO?ods_study_1.ods_study_join_a(study_id_a)?VALUES(1),(2),(3),(4),(5)
INSERT?INTO?ods_study_1.ods_study_join_b(study_id_b,study_channel)?VALUES(1,'weixin'),(2,'zhihu'),(2,'zhihu'),(3,'toutiao');
2、查看一下原始的數(shù)據(jù):

結(jié)果驗(yàn)證
將上面的兩個(gè)表Inner Join和Left Join,過濾條件分別放在on和where中。
1、Inner Join時(shí)
ON中設(shè)置過濾條件
SELECT?
?*
FROM?
?ods_study_1.ods_study_join_a?A
Inner?JOIN?
?ods_study_1.ods_study_join_b?B
ON?(A.study_id_a?=?B.study_id_b?AND?B.study_channel='weixin')
返回結(jié)果:
Where中設(shè)置過濾條件
SELECT?
?*
FROM?
?ods_study_1.ods_study_join_a?A
Inner?JOIN?
?ods_study_1.ods_study_join_b?B
ON?(A.study_id_a?=?B.study_id_b?)
WHERE?B.study_channel='weixin'
返回結(jié)果:
結(jié)論:Inner Join時(shí)過濾條件放在on和where中返回結(jié)果一致。
2、Left Join時(shí)
ON中設(shè)置過濾條件
SELECT?
?*
FROM?
?ods_study_1.ods_study_join_a?A
LEFT?JOIN?
?ods_study_1.ods_study_join_b?B
ON?(A.study_id_a?=?B.study_id_b?AND?B.study_channel='weixin')
返回結(jié)果:
Where中設(shè)置過濾條件
SELECT?
?*
FROM?
?ods_study_1.ods_study_join_a?A
LEFT?JOIN?
?ods_study_1.ods_study_join_b?B
ON?(A.study_id_a?=?B.study_id_b?)
WHERE?B.study_channel='weixin'
返回結(jié)果:
結(jié)論:Left Join時(shí)過濾條件放在on和where中返回結(jié)果不一致。
原因分析
可以這么理解,當(dāng)兩張表在Left Join時(shí),會(huì)生成一張連接臨時(shí)表,然后再將這張連接臨時(shí)表返回給用戶。
在On的情況下,是在生成臨時(shí)表時(shí)起作用,但由于Left Join的性質(zhì),就是他不管On里面的過濾條件是否為真,都會(huì)返回左表里的記錄。對于不滿足條件的記錄,右表字段全部是NULL。
在Where的情況下,是在臨時(shí)表生成好以后起作用,在對臨時(shí)表進(jìn)行過濾。此時(shí),只要條件不為真的行,全部都過濾掉了。
送幾本書給大家,參與問題留言討論,留言討論中選5位,本文發(fā)出后越早留言的可能獲得書的概率更大,理由是那會(huì)我會(huì)細(xì)看大家的留言。
唯一要求:真實(shí)。
如果你覺得本文確實(shí)寫的還行,對你有所收獲,請給寶器一個(gè)在看。
送書信息:

寶器2020年11月7日于廣東。
