SQL中JOIN時(shí)條件放在Where和On的區(qū)別
設(shè)為“置頂或星標(biāo)”,第一時(shí)間送達(dá)干貨
背景
SQL中JOIN子句是用于把來(lái)自兩個(gè)或多個(gè)表的數(shù)據(jù)連接起來(lái),在這個(gè)過(guò)程中可能會(huì)添加一些過(guò)濾條件。昨天有小伙伴問(wèn),如下圖的這兩種SQL寫(xiě)法查詢結(jié)果是否會(huì)一樣?(好像這是某一年阿里的面試題)

這個(gè)問(wèn)題提出來(lái)以后,多數(shù)小伙伴的回答是:查詢結(jié)果應(yīng)該是一樣的吧,只是查詢效率不一樣。我當(dāng)時(shí)的回答是,在Inner Join時(shí)這兩種情況返回的結(jié)果是一樣的,在Left、Right等情況時(shí)結(jié)果不一樣。
案例
1、創(chuàng)建測(cè)試數(shù)據(jù)庫(kù)和表并且插入用戶測(cè)試的數(shù)據(jù)。
--?創(chuàng)建數(shù)據(jù)庫(kù)
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,過(guò)濾條件分別放在on和where中。
1、Inner Join時(shí)
ON中設(shè)置過(guò)濾條件
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è)置過(guò)濾條件
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í)過(guò)濾條件放在on和where中返回結(jié)果一致。
2、Left Join時(shí)
ON中設(shè)置過(guò)濾條件
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è)置過(guò)濾條件
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í)過(guò)濾條件放在on和where中返回結(jié)果不一致。
原因分析
可以這么理解,當(dāng)兩張表在Left Join時(shí),會(huì)生成一張連接臨時(shí)表,然后再將這張連接臨時(shí)表返回給用戶。
在On的情況下,是在生成臨時(shí)表時(shí)起作用,但由于Left Join的性質(zhì),就是他不管On里面的過(guò)濾條件是否為真,都會(huì)返回左表里的記錄。對(duì)于不滿足條件的記錄,右表字段全部是NULL。
在Where的情況下,是在臨時(shí)表生成好以后起作用,在對(duì)臨時(shí)表進(jìn)行過(guò)濾。此時(shí),只要條件不為真的行,全部都過(guò)濾掉了。
——End——
后臺(tái)回復(fù)關(guān)鍵字:1024,獲取一份精心整理的技術(shù)干貨 后臺(tái)回復(fù)關(guān)鍵字:進(jìn)群,帶你進(jìn)入高手如云的交流群。 推薦閱讀
SQL 語(yǔ)句中 where 條件后 寫(xiě)上1=1 是什么意思 國(guó)產(chǎn)數(shù)據(jù)庫(kù)建模工具,看到界面第一眼,良心了! 快手公司廁所裝坑位計(jì)時(shí)器,網(wǎng)友:再也不能帶薪拉屎了! 如何優(yōu)雅地給妹子優(yōu)化電腦? 最全MySQL面試題集合 這是一個(gè)能學(xué)到技術(shù)的公眾號(hào),歡迎關(guān)注
點(diǎn)擊「閱讀原文」了解SQL訓(xùn)練營(yíng)
