目前hive不支持 in或not in 中包含查詢子句的語法,所以只能通過left join實現。
假設有一個登陸表login(當天登陸記錄,只有一個uid),和一個用戶注冊表regusers(當天注冊用戶,字段只有一個uid),這兩個表都包含一個字段,uid。
in查詢
如果要查詢當天登陸的注冊用戶,需要用in查詢,hive sql如下:
select login.uid from login left outer join regusers on login.uid=regusers.uid where regusers.uid is not null
如果login表和regusers表按天分區,字段是dt,那么查詢2013年1月1號當天登陸的注冊用戶,hive sql如下:
select login.uid from login day_login left outer join (select uid from regusers where dt='20130101') day_regusers on day_login.uid=day_regusers.uid where day_login.dt='20130101' and day_regusers.uid is not null
not in查詢
如果要查詢當天登陸的老用戶(這里假設非當天注冊用戶就是老用戶),需要用not in查詢,hive sql如下:
select login.uid from login left outer join regusers on login.uid=regusers.uid where regusers.uid is null;
如果login表和regusers表按天分區,字段是dt,那么查詢2013年1月1號當天登陸的老用戶,hive sql如下:
select login.uid from login day_login left outer join (select uid from regusers where dt='20130101') day_regusers on day_login.uid=day_regusers.uid where day_login.dt='20130101' and day_regusers.uid is null;
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)
笛卡爾積
Hive本身是不支持笛卡爾積的,不能用select T1.*, T2.* from table_1, table_2這種語法。但有時候確實需要用到笛卡爾積的時候,可以用下面的語法來實現同樣的效果:
其中on 1=1是可選的,注意在Hive的Strict模式下不能用這種語法,需要先用set hive.mapred.mode=nonstrict;設為非strict模式就可以用了。