Join是关系型数据库系统的重要操做之一,通常关系型数据库中包含的经常使用Join:内联接、外联接和交叉联接等。若是咱们想在两个或以上的表获取其中从一个表中的行与另外一个表中的行匹配的数据,这时咱们应该考虑使用Join,本文将经过可视化图表介绍SQL中的各类经常使用Join特性、原理和使用场景:html
create table table_1 ( `id` INT (11) NOT NULL, user_name varchar(20) NOT NULL ) create table table_2 ( `id` INT (11) NOT NULL, user_name varchar(20) NOT NULL ) set sql_safe_updates=0; insert into table_1 values (1,"zhangsan_1_1"),(2,"lisi_1_1"),(3,"wangmazi_1"),(1,"zhangsan_1_2"),(2,"lisi_1_2"); select * from table_1 -- DELETE from table_1 insert into table_2 values (4,"zhaoliu_2_1"),(2,"lisi_2_1"),(3,"wangmazi_2_1"),(1,"zhangsan_2"),(2,"lisi_2_2"),(4,"zhaoliu_2_2"),(3,"wangmazi_2_2") -- DELETE from table_2 select * from table_2 SELECT * FROM table_1 t1 INNER JOIN table_2 t2 ON t1.id = t2.id; SELECT * FROM table_1 t1 WHERE EXISTS (SELECT 1 FROM table_2 t2 WHERE t2.id = t1.id ); -- 结果集:1+2==3 -- 一、inner join: SELECT * FROM table_1 t1, table_2 t2 where t1.id = t2.id; -- 二、anti-join: SELECT * FROM table_1 t1, table_2 t2 where t1.id != t2.id; -- 三、cross join:select * from table_1 t1, table_2 t2; -- 不带条件等同于 cross join SELECT * FROM table_1 t1 WHERE EXISTS (SELECT 1 FROM table_2 t2 WHERE t2.id = t1.id ); 1 zhangsan_1_1 2 lisi_1_1 3 wangmazi_1 1 zhangsan_1_2 2 lisi_1_2 SELECT * FROM table_1 t1 INNER JOIN table_2 t2 ON t1.id = t2.id; 2 lisi_1_1 2 lisi_2_1 2 lisi_1_2 2 lisi_2_1 3 wangmazi_1 3 wangmazi_2_1 1 zhangsan_1_1 1 zhangsan_2 1 zhangsan_1_2 1 zhangsan_2 2 lisi_1_1 2 lisi_2_2 2 lisi_1_2 2 lisi_2_2 3 wangmazi_1 3 wangmazi_2_2
Semi Join 也叫半链接,Semi-join从一个表中返回的行与另外一个表中数据行进行不彻底联接查询(查找到匹配的数据行就返回,再也不继续查找)。mysql
Anti-semi-join从一个表中返回的行与另外一个表中数据行进行不彻底联接查询,而后返回不匹配的数据。sql
不一样于其余的联接运算,Semi-join和Anti-semi-join没有明确的语法来实现,但Semi-join和Anti-semi-join在RDBMS中有多种应用场合。咱们能够使用EXISTS/IN子句来实现Semi-join查询,Not EXISTS来实现Anti-semi-join。数据库
# select dname from dept where exists( select null from emp where emp.deptno=dept.deptno) for x in ( select * from dept ) loop for y in ( select * from emp) loop if ( x.deptno == y.deptno ) OutPut_Record(x.dname) # 多在子查询exists中使用,对外部row source的每一个键值,查找到内部row source匹配的第一个键值后就返回,若是找到就不用再查找内部row source其余的键值了。 Break; End if end loop end loop # select ename,deptno from emp,dept where emp.deptno!=dept.deptno # 多用于!= not in 等查询;若是找到知足条件(!= not in)的不返回,不知足条件(!= not in)的返回。和 join 相反。 # for example: nested loop anti-join for x in ( select * from emp ) loop for y in ( select * from dept) loop if ( x.deptno != y.deptno ) OutPut_Record(x.dname,y.deptno) End if end loop end loop
具体看这个 case 就能体会其中的差异,以及须要注意的坑:bash
[0] Hive 中的 LEFT SEMI JOIN 与 JOIN ON 的前世此生oop
https://my.oschina.net/leejun2005/blog/188459post
注:spa
一、mysql并不支持 full outer join .net
二、outer、inner 关键字在常见数据库SQL中通常能够省略code
三、在早期HIVE版本中,并不支持 Exist/IN 子查询,而是在 0.5 以后提供了 left semi join 语法
四、注意 Anti-semi-join 与 anti-join 区别
五、select * from A,B; 不带 where 或者 join 等同于 cross join,带 where 或 等同于 inner join
六、left semi join 中最后 select 的结果只许出现左表,由于右表只有 join key 参与关联计算了,而 join on 默认是整个关系模型都参与计算了
七、对待右表中重复key的处理方式差别:由于 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join on 则会一直遍历作 key 内 cross join
[0] 看漫画就能学SQL,简直太cool了
https://mp.weixin.qq.com/s/t8JCJSP__qh11U2zl8hCeQ
[1] Say NO to Venn Diagrams When Explaining JOINs
https://blog.jooq.org/2016/07/05/say-no-to-venn-diagrams-when-explaining-joins/
[2] SQL Server Join Types Poster (Version 2)
http://stevestedman.com/2015/03/sql-server-join-types-poster-version-2/
[3] SQL Join的一些总结
http://www.cnblogs.com/rush/archive/2012/03/27/2420246.html
[4] 简单介绍join,outer-join,semi-join,anti-join的区别
http://blog.csdn.net/wanghai__/article/details/6426941
[5] Spark SQL 之 Join 实现