一、LEFT SEMI JOIN 與 INNER JOIN的區別
1. LEFT SEMI JOIN
LEFT SEMI JOIN 是 IN/EXISTS 子查詢的一種更高效的實現。
Hive 當前沒有實現 IN/EXISTS 子查詢,所以你可以用 LEFT SEMI JOIN 重寫子查詢語句。LEFT SEMI JOIN 的限制是, JOIN 子句中右邊的表只能在 ON 子句中設置過濾條件,在 WHERE 子句、SELECT 子句或其他地方過濾都不行。
SELECT a.key, a.value
FROM a
WHERE a.key in
(SELECT b.key
FROM B);
可以被重寫爲:
SELECT a.key, a.val
FROM a LEFT SEMI JOIN b on (a.key = b.key)
2.INNER JOIN
INNER JOIN 等價於 JOIN,可以理解爲 JOIN是 INNER JOIN 的縮寫。
3.區別
HIVE中都是等值連接,在JOIN使用的時候,有兩種寫法在理論上是可以達到相同的效果的,但是由於實際情況的不一樣,子表中數據的差異導致結果也不太一樣。
當子表(tab2)中存在重複的數據,當使用JOIN ON的時候,A,B表會關聯出兩條記錄,應爲ON上的條件符合;而是用LEFT SEMI JOIN 當A表中的記錄,在B表上產生符合條件之後就返回,不會再繼續查找B表記錄了,所以如果B表有重複,也不會產生重複的多條記錄。
二、數據樣例測試
1、造測試數據
drop table if exists tmp.tab1;
create table tmp.tab1 as
select 1 id,'a' name,90 score
union all
select 2 id,'b' name,80 score
union all
select 3 id,'c' name,85 score;
drop table if exists tmp.tab2;
create table tmp.tab2 as
select 2 id,'b' name,80 score
union all
select 3 id,'c' name,85 score
union all
select 4 id,'d' name,90 score;
2、查詢測試
2.1、LEFT JOIN=LEFT OUTER JOIN
SELECT a1.id,
a1.name,
a1.score
FROM tmp.tab1 a1
LEFT JOIN tmp.tab2 a2 ON a1.id=a2.id;
OK
1 a 90
2 b 80
3 c 85
Time taken: 19.636 seconds, Fetched: 3 row(s)
SELECT a1.id,
a1.name,
a1.score
FROM tmp.tab1 a1
LEFT OUTER JOIN tmp.tab2 a2 ON a1.id=a2.id;
OK
1 a 90
2 b 80
3 c 85
Time taken: 17.025 seconds, Fetched: 3 row(s)
2.2、LEFT SEMI JOIN ~= INNER JOIN
SELECT a1.id,
a1.name,
a1.score
FROM tmp.tab1 a1 LEFT SEMI
JOIN tmp.tab2 a2 ON a1.id=a2.id;
OK
2 b 80
3 c 85
Time taken: 20.815 seconds, Fetched: 2 row(s)
SELECT a1.id,
a1.name,
a1.score
FROM tmp.tab1 a1
INNER
JOIN tmp.tab2 a2 ON a1.id=a2.id;
OK
2 b 80
3 c 85
Time taken: 20.791 seconds, Fetched: 2 row(s)
2.3、全連接
SELECT a1.id,
a1.name,
a1.score
FROM tmp.tab1 a1
FULL
JOIN tmp.tab2 a2 ON a1.id=a2.id;
OK
1 a 90
2 b 80
3 c 85
NULL NULL NULL
Time taken: 20.102 seconds, Fetched: 4 row(s)