圖文並茂詳解 SQL JOIN

Join是關係型數據庫系統的重要操做之一,通常關係型數據庫中包含的經常使用Join:內聯接、外聯接和交叉聯接等。若是咱們想在兩個或以上的表獲取其中從一個表中的行與另外一個表中的行匹配的數據,這時咱們應該考慮使用Join,本文將經過可視化圖表介紹SQL中的各類經常使用Join特性、原理和使用場景:html

一、INNER JOIN && OUTER JOIN

venn-join

二、CROSS JOIN

venn-cross-join

三、韋恩圖 JOIN 全解

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

joinTypeThumbnail

四、特殊 Join:Semi-join 和 Anti-semi-join

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

REF:

[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 實現

https://cloud.tencent.com/community/article/709612

相關文章
相關標籤/搜索