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;``` 
SELECT count(t2.id)
FROM name t1 LEFT JOIN classes t2 ON t1.grade = t2.id;
 这里能够看到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)