问题解决:hive中的find_in_set不能用作join的条件

假设有两个表A和B,其中:

表A

id

1

2

3

4

5


表B

ids

1,2,3

2,3

4,5

5,6

7,8

这里B中的ids字段是许多由逗号分隔的id。现在的任务是join两张表,条件是A.id要出现在B.ids中。

如果在mysql中,使用语句:

select * from A
join B
on find_in_set(A.id,B.ids) != 0;
可得结果

id      ids
1	1,2,3
2	1,2,3
3	1,2,3
2	2,3
3	2,3
4	4,5
5	4,5
5	5,6
可以看到结果是正常的。

但是如果在hive中出入该语句,则提示错误Both left and right aliases encountered in JOIN '0' 。原因在于hive中不支持非等值连接。

————————————————————————————————————————

补充,这里的“等值连接”不是说把“!=”换成“=”就可以,事实上更改之后错误依旧。个人理解这里的“等值连接”是指做关联的两个字段一定要出现在等式的两侧,写成数学形式就是:function1(A.id) = function2(B.ids)

————————————————————————————————————————

如何解决?前提是不涉及过多编程,只用hive自带函数。

可采用如下方法:

select A.id from
(select explode(split(ids,",")) as id from B) t
join A
on t.id = A.id
先将ids按逗号分割成数组,然后行转列,这样就可以进行join了。

得到结果如下:

A.id
1
2
3
2
3
4
5
5

可以看到与mysql的结果是一致的。

当然,实际工作中的寻量很复杂的,要考虑很多条件与限制。

————————————————————————————————————————

补充。比如说B中的字段是这样的 id分隔符XXX分隔符XXX。如果确认id出现的位置和长度保持不变,用substring函数截取字符串就可以。如果仅确认位置不变,可以用regexp_extract函数进行正则比配,不过速度就要比subtring慢很多了。

————————————————————————————————————————


P.S.本人在stackoverflow上提了类似的问题:https://stackoverflow.com/questions/44110635/how-to-join-tables-in-hive-using-find-in-set 不过至今没有人回答

你可能感兴趣的:(Hadoop)