Hive 实现 IN 和 NOT IN 子句 和 LEFT SEMI JOIN 应用

目前hive不支持 in或not in 中包含查询子句的语法,所以只能通过left join实现。

假设有一个用户浏览商品表skim,和一个用户购买商品表buy。如下

skim表

userId itemId time
001 342 2015-05-08
002 382 2015-05-09
003 458 2015-05-09
004 468 2015-05-09

buy表

userId itemId time
001 342 2015-05-07
002 382 2015-05-08
003 458 2015-05-09
005 325 2015-05-09

select * from skim left outer join buy 
on skim.userId = buy .userId and skim.itemId = buy .itemId 
结果如下:

skim.userId skim.itemId skim.time buy.userId buy.itemId buy.time
001 342 2015-05-08 001 342 2015-05-08
002 382 2015-05-09 002 382 2015-05-09
003 458 2015-05-09 003 458 2015-05-09
004 468 2015-05-09      

IN

如果要查询在skim表中并且也在buy表中的信息,需要用in查询,hive sql如下:

select skim.userId , skim.itemId from skim left outer join buy 
on skim.userId = buy .userId and skim.itemId = buy .itemId where buy .userId is not null;

结果如下:

userId itemId
001 342
002 382
003 458

NOT IN

如果要查询在skim表中并且不也在buy表中的信息,需要用not in查询,hive sql如下:

select skim.userId, skim.itemId from skim left outer join buy 
on skim.userId=buy .userId and skim.itemId=buy .itemId where buy .userId is null;

结果如下:

userId itemId
004 468

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这种语法。但有时候确实需要用到笛卡尔积的时候,可以用下面的语法来实现同样的效果:

select T1.*, T2.* from (select * from table1) T1 join (select * from table2) T2 on 1=1;

其中on 1=1是可选的,注意在Hive的Strict模式下不能用这种语法,需要先用set hive.mapred.mode=nonstrict;设为非strict模式就可以用了。



猜你喜欢

转载自blog.csdn.net/haijiege/article/details/80423695