mysql中的left join、right join、join

sql準備

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, '溜噠');

table_name

table_classes.png


各類join的使用

left join 即爲以sql語句中的左邊的表爲主要表關聯右邊的表,其中使用on做爲條件篩選,where爲過濾條件mysql

以name爲主表,classes爲關聯表
SELECT *
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id;

name_left_join_classes.png

left_join.png

能夠看到小花和小綠並無關聯到classes中的任何數據,咱們以name爲左表,而後以classes爲右表而後進行關聯,展現5行數據,條件不符合的小花和小綠(沒有想對應的班級、師傅領養),即爲野生,須要使用null補全,而溜噠同窗乾脆直接無視。sql

以classes爲主表以name爲關聯表
SELECT *
FROM name t1 RIGHT JOIN classes t2 ON t1.grade = t2.id;

name_right_join_classes.png

right_join.png

能夠看到以classes爲主表,以name爲關聯表結果爲4條,雖然溜噠同窗什麼也不會,可是仍是能夠下班以後溜噠溜噠溜溜狗的嘛(單身狗也是狗)!!數據庫

無主次關聯join(inner join)

SELECT *
FROM name t1 JOIN classes t2 ON t1.grade = t2.id;

name_join_classes

join(inner join).png
而join能夠看到只有兩個表徹底的交集才能被顯示出來,這裏顯示3條。果真,最後登上光明頂的仍是名師下邊的高徒。我等能夠繼續溜噠溜噠。性能

傳說中的full join(mysql不支持,使用union來進行模擬)

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;

union_left_right.png

full_join.png

能夠看到,full join表示全並集,即6條數據。論起溜噠溜噠溜溜單身汪,溜噠同窗仍是能夠的。優化

綜上所述,能夠整理獲得:以哪一個表爲主表則檢索出哪一個表的所有內容,關聯表中符合on關聯要求的能夠進行數據關聯,若是不符合要求,那麼須要以null行展現;若是使用join進行關聯那麼無主次關聯,只顯示符合要求的數據。spa


on、where的使用

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);

left_join_on_where.png
而後,把where中的條件拿到on中code

SELECT *
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id AND t2.id IN(1,3);

left_join_on_no_where.png

能夠看到,加上where條件後做用再left join on關聯後的數據,將不符合where條件的所有去掉,只使用on,和咱們先前獲得的結論一致,不符合關聯條件的須要null行補充。索引

on where 約束力相同的時候

先回顧一下join(inner join)。ip

SELECT *
FROM name t1 JOIN classes t2 ON t1.grade = t2.id AND t2.id IN(1,3);

join(inner join).png
獲得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);

join_where.png
能夠看到,此處的t2.id IN(1,3)在on和在where中效果同樣。溜噠同窗表示能夠理解爲是join關鍵詞形成的,應爲join表示徹底符合條件的才進行關聯展現,不會進行數據null行補充,而where用於過濾數據,那麼也是表示符合條件的進行展現。(若是問我爲啥不把 t1.grade = t2.id也拿到where中去,那麼同窗能夠本身動手試試嘛!)

各類join、on、where該怎麼聯合使用

首先拿出最開始的例子,普通left join和on使用,展現5條數據。

SELECT *
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id

left_join_on.png
而後咱們進行數據統計,使用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);`
left_join_on_no_where.png

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);

error_count(age).png

SELECT sum(t1.age)
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id 
WHERE t2.id IN(1, 3);

right_count(age).png
那麼有沒有可能不用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);

name.age+classes.id_on.png

SELECT t1.age+t2.id
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id
WHERE t2.id IN(1, 3);

name.age+classes.id_where.png
如上,兩部分進行了加和計算操做,這時候若是再進行sum()等統計操做,其實出來的數據是同樣的。使用規範,看你所在團隊更傾向於哪種。固然,若是這裏使用join 內鏈接,那麼就沒有這麼多不一樣了。


關於性能

首先必須明確的事情就是:

  1. 使用關聯確定是要從關聯表中拿數據進行展現。
  2. 數據庫輸出的數據越多,性能越低。
  3. 數據庫有本身的優化引擎,可能會將你的sql語句進行自我優化。

溜噠同窗自己技術很差,此次不進行性能討論,從輸出上來看join性能要好一些,可是在工做中會存在明顯的left join比join快的狀況,網上都是說select中的統計並無用到關聯表的數據,因此存在數據庫優化將關聯表不進行關聯,而後直接進行統計的狀況,此時,join仍是須要進行關聯(雙向的), 因此會出現left join 比join快的狀況。同時也會出現索引使用的問題。固然這只是網上的文章,不是本身操做的沒有辦法說服本身,仍是多看看書,作點小實驗明確一下。(會有人看麼?衰.jpg)

相關文章
相關標籤/搜索