INSERT INTO name(name, age, grade) VALUES ('小白', 20, 1), ('小黑', 21, 2), ('小紅', 22, 3), ('小花', 23, 4), ('小綠', 24, 5) ; INSERT INTO classes (cname) VALUES ('歐陽鋒'), ('楊過'), ('喬峯'); INSERT INTO classes (id,cname) VALUES (7, '溜噠');
left join 即爲以sql語句中的左邊的表爲主要表關聯右邊的表,其中使用on做爲條件篩選,where爲過濾條件mysql
SELECT * FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id;
能夠看到小花和小綠並無關聯到classes中的任何數據,咱們以name爲左表,而後以classes爲右表而後進行關聯,展現5行數據,條件不符合的小花和小綠(沒有想對應的班級、師傅領養),即爲野生,須要使用null補全,而溜噠同窗乾脆直接無視。sql
SELECT * FROM name t1 RIGHT JOIN classes t2 ON t1.grade = t2.id;
能夠看到以classes爲主表,以name爲關聯表結果爲4條,雖然溜噠同窗什麼也不會,可是仍是能夠下班以後溜噠溜噠溜溜狗的嘛(單身狗也是狗)!!數據庫
SELECT * FROM name t1 JOIN classes t2 ON t1.grade = t2.id;
而join能夠看到只有兩個表徹底的交集才能被顯示出來,這裏顯示3條。果真,最後登上光明頂的仍是名師下邊的高徒。我等能夠繼續溜噠溜噠。性能
SELECT * FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id UNION SELECT * FROM name t1 RIGHT JOIN classes t2 ON t1.grade = t2.id;
能夠看到,full join表示全並集,即6條數據。論起溜噠溜噠溜溜單身汪,溜噠同窗仍是能夠的。優化
綜上所述,能夠整理獲得:以哪一個表爲主表則檢索出哪一個表的所有內容,關聯表中符合on關聯要求的能夠進行數據關聯,若是不符合要求,那麼須要以null行展現;若是使用join進行關聯那麼無主次關聯,只顯示符合要求的數據。spa
on:兩個表關聯的時候使用,決定被關聯的表的數據是否能與主表關聯(name left join classes on name.grade = classes.id)主表name數據徹底顯示,不被關聯的數據須要在grade側以null數據補全
where:兩個表關聯後,再進行條件過濾
區別:on主要做用再被關聯表中,where做用在關聯後的左右數據上3d
SELECT * FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id WHERE t2.id IN (1, 3);
而後,把where中的條件拿到on中code
SELECT * FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id AND t2.id IN(1,3);
能夠看到,加上where條件後做用再left join on關聯後的數據,將不符合where條件的所有去掉,只使用on,和咱們先前獲得的結論一致,不符合關聯條件的須要null行補充。索引
先回顧一下join(inner join)。ip
SELECT * FROM name t1 JOIN classes t2 ON t1.grade = t2.id AND t2.id IN(1,3);
獲得join條件的兩條數據。若是咱們把追加的t2.id in(1,3)拿到where中是什麼狀況呢?
SELECT * FROM name t1 JOIN classes t2 ON t1.grade = t2.id WHERE t2.id IN(1,3);
能夠看到,此處的t2.id IN(1,3)在on和在where中效果同樣。溜噠同窗表示能夠理解爲是join關鍵詞形成的,應爲join表示徹底符合條件的才進行關聯展現,不會進行數據null行補充,而where用於過濾數據,那麼也是表示符合條件的進行展現。(若是問我爲啥不把 t1.grade = t2.id也拿到where中去,那麼同窗能夠本身動手試試嘛!)
首先拿出最開始的例子,普通left join和on使用,展現5條數據。
SELECT * FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id
而後咱們進行數據統計,使用count()來進行查看數據條數。
SELECT count(t1.id) FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id;``` ![count(name.id).png](http://upload-images.jianshu.io/upload_images/3935727-d3d73cdfd053008b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
SELECT count(t2.id)
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id;
![count(classes.id).png](http://upload-images.jianshu.io/upload_images/3935727-9ffa8ca198c539a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 這裏能夠看到count(null)是不計入數據統計的(不要問爲何),那麼能夠看出,關聯後的統計在各自部分統計是沒有什麼問題的,name表側是5條,而符合on條件的classes側是3條。由此,能夠引伸出另外一個容易出錯的地方:在on中若是有多個條件進行關聯限制,此時若是這些條件中有想進行過濾的那麼須要拿到where中去,纔會進行正確數據篩選。 ####多on條件搭配where使用(不要用錯)
SELECT *
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id AND t2.id IN(1, 3);`
count(t1.id) = 5
count(t2.id) = 2
這裏若是想要統計符合classes.id in(1,3)的數據的時候,必定要把t2.id in(1,3)拿到where中去。好比,但願統計西毒、喬峯這兩個前輩的高徒的年齡和須要將t2.id in(1,3)放到where中去。
SELECT sum(t1.age) FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id AND t2.id IN(1, 3);
SELECT sum(t1.age) FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id WHERE t2.id IN(1, 3);
那麼有沒有可能不用where數據也能統計對的狀況呢?
必然有(就好像數學老師說,這道題選A對不對啊??大多數狀況下不對。。。),兩個表進行關聯,不使用where,可是當兩部分有計算操做的時候,效果是理想的。
咱們操做name中的age去加上classes中的id,(就當作師傅給徒弟傳各自id數值的年限的內力)
SELECT t1.age+t2.id FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id AND t2.id IN(1, 3);
SELECT t1.age+t2.id FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id WHERE t2.id IN(1, 3);
如上,兩部分進行了加和計算操做,這時候若是再進行sum()等統計操做,其實出來的數據是同樣的。使用規範,看你所在團隊更傾向於哪種。固然,若是這裏使用join 內鏈接,那麼就沒有這麼多不一樣了。
首先必須明確的事情就是:
溜噠同窗自己技術很差,此次不進行性能討論,從輸出上來看join性能要好一些,可是在工做中會存在明顯的left join比join快的狀況,網上都是說select中的統計並無用到關聯表的數據,因此存在數據庫優化將關聯表不進行關聯,而後直接進行統計的狀況,此時,join仍是須要進行關聯(雙向的), 因此會出現left join 比join快的狀況。同時也會出現索引使用的問題。固然這只是網上的文章,不是本身操做的沒有辦法說服本身,仍是多看看書,作點小實驗明確一下。(會有人看麼?衰.jpg)