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为过滤条件

以name为主表,classes为关联表
SELECT *
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id;```

![name_left_join_classes.png](http://upload-images.jianshu.io/upload_images/3935727-dc35138c87647312.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![left_join.png](http://upload-images.jianshu.io/upload_images/3935727-0c35f5273a45b918.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

可以看到小花和小绿并没有关联到classes中的任何数据,我们以name为左表,然后以classes为右表然后进行关联,展示5行数据,条件不符合的小花和小绿(没有想对应的班级、师傅领养),即为野生,需要使用null补全,而溜哒同学干脆直接无视。
#####以classes为主表以name为关联表
```sql
SELECT *
FROM name t1 RIGHT JOIN classes t2 ON t1.grade = t2.id;```


![name_right_join_classes.png](http://upload-images.jianshu.io/upload_images/3935727-bd7e9747b9b38dee.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


![right_join.png](http://upload-images.jianshu.io/upload_images/3935727-cfff64e069a8dd15.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


可以看到以classes为主表,以name为关联表结果为4条,虽然溜哒同学什么也不会,但是还是可以下班之后溜哒溜哒溜溜狗的嘛(单身狗也是狗)!!
####无主次关联join(inner join)
```sql
SELECT *
FROM name t1 JOIN classes t2 ON t1.grade = t2.id;```


![name_join_classes](http://upload-images.jianshu.io/upload_images/3935727-8e4d3118d3d2fdf4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)



![join(inner join).png](http://upload-images.jianshu.io/upload_images/3935727-0a915919061d8a54.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
而join可以看到只有两个表完全的交集才能被显示出来,这里显示3条。果然,最后登上光明顶的还是名师下边的高徒。我等可以继续溜哒溜哒。

####传说中的full join(mysql不支持,使用union来进行模拟)
```sql
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](http://upload-images.jianshu.io/upload_images/3935727-4393a8ae2701705e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


![full_join.png](http://upload-images.jianshu.io/upload_images/3935727-1c297e094666b8db.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

可以看到,full join表示全并集,即6条数据。论起溜哒溜哒溜溜单身汪,溜哒同学还是可以的。



综上所述,可以整理得到:以哪个表为主表则检索出哪个表的全部内容,关联表中符合on关联要求的可以进行数据关联,如果不符合要求,那么需要以null行展示;如果使用join进行关联那么无主次关联,只显示符合要求的数据。
***
#on、where的使用
on:两个表关联的时候使用,决定被关联的表的数据是否能与主表关联(name left join classes on name.grade = classes.id)主表name数据完全显示,不被关联的数据需要在grade侧以null数据补全
where:两个表关联后,再进行条件过滤
区别:on主要作用再被关联表中,where作用在关联后的左右数据上
####基本作用
```sql
SELECT *
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id
WHERE t2.id IN (1, 3);```

![left_join_on_where.png](http://upload-images.jianshu.io/upload_images/3935727-aa902f2c80f9b5c8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
然后,把where中的条件拿到on中
```sql
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](http://upload-images.jianshu.io/upload_images/3935727-117623b6cc6dd2e5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

可以看到,加上where条件后作用再left join  on关联后的数据,将不符合where条件的全部去掉,只使用on,和我们先前得到的结论一致,不符合关联条件的需要null行补充。
####on where 约束力相同的时候
先回顾一下join(inner join)。

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

![join(inner join).png](http://upload-images.jianshu.io/upload_images/3935727-58751c62ecc35e12.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
得到join条件的两条数据。如果我们把追加的t2.id in(1,3)拿到where中是什么情况呢?

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

![join_where.png](http://upload-images.jianshu.io/upload_images/3935727-58751c62ecc35e12.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以看到,此处的t2.id IN(1,3)在on和在where中效果一样。溜哒同学表示可以理解为是join关键词造成的,应为join表示完全符合条件的才进行关联展示,不会进行数据null行补充,而where用于过滤数据,那么也是表示符合条件的进行展示。(如果问我为啥不把 t1.grade = t2.id也拿到where中去,那么同学可以自己动手试试嘛!)
####各种join、on、where该怎么联合使用
首先拿出最开始的例子,普通left join和on使用,展示5条数据。
```sql
SELECT *
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id```

![left_join_on.png](http://upload-images.jianshu.io/upload_images/3935727-528eb3a49913b0a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
然后我们进行数据统计,使用count()来进行查看数据条数。
```sql
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)
```sql
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使用(不要用错)
```sql
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](http://upload-images.jianshu.io/upload_images/3935727-117623b6cc6dd2e5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

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中去。
```sql
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](http://upload-images.jianshu.io/upload_images/3935727-124b9e436f939a0e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

```sql
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](http://upload-images.jianshu.io/upload_images/3935727-3d43583862fdc403.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
那么有没有可能不用where数据也能统计对的情况呢?
必然有(就好像数学老师说,这道题选A对不对啊??大多数情况下不对。。。),两个表进行关联,不使用where,但是当两部分有计算操作的时候,效果是理想的。
我们操作name中的age去加上classes中的id,(就当做师傅给徒弟传各自id数值的年限的内力)
```sql
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](http://upload-images.jianshu.io/upload_images/3935727-279b6410b0dbf59f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

```sql
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](http://upload-images.jianshu.io/upload_images/3935727-d69ad90f7c96c2cc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
如上,两部分进行了加和计算操作,这时候如果再进行sum()等统计操作,其实出来的数据是一样的。使用规范,看你所在团队更倾向于哪一种。当然,如果这里使用join 内连接,那么就没有这么多不同了。
***
####关于性能
首先必须明确的事情就是:
1. 使用关联肯定是要从关联表中拿数据进行展示。
2. 数据库输出的数据越多,性能越低。
3. 数据库有自己的优化引擎,可能会将你的sql语句进行自我优化。
***
溜哒同学本身技术不好,这次不进行性能讨论,从输出上来看join性能要好一些,但是在工作中会存在明显的left join比join快的情况,网上都是说select中的统计并没有用到关联表的数据,所以存在数据库优化将关联表不进行关联,然后直接进行统计的情况,此时,join还是需要进行关联(双向的), 所以会出现left join 比join快的情况。同时也会出现索引使用的问题。
当然这只是网上的文章,不是自己操作的没有办法说服自己,还是多看看书,做点小实验明确一下。这是溜哒同学第一篇博客,请大家轻拍!!(会有人看么?衰.jpg)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容