假设有两个表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 不过至今没有人回答