模拟hive中的间隔连接

时间:2014-08-20 09:47:39

标签: join hive

我正在使用hive 0.13。

我有两张桌子:

  1. 数据表。列:id,时间。 1E10行。
  2. mymap表格。 columns:id,name,start_time,end_time。 1E6行。
  3. 对于数据表中的每一行,我想从mymap表中获取与id和时间间隔匹配的名称。所以我想做一个像:

    这样的联接
    select data.id, time, name from data left outer join mymap on data.id = mymap.id and time>=start_time and time<end_time
    

    众所周知,对于数据中的每一行,mymap中都有0或1个匹配。

    配置单元不支持上述查询,因为它是非等连接。将不等式条件移动到where过滤器不起作用会导致连接在应用过滤器之前爆炸:

    select data.id, time, name from data left outer join mymap on data.id = mymap.id where mymap.id is null or (time>=start_time and time<end_time)
    

    (我知道由于id匹配但没有匹配间隔的情况,查询不完全等效。这可以按照我在此处描述的那样解决:Hive: work around for non equi left join

    我该如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

您可以执行加入,然后从该表进行查询。我没有测试这段代码,但它会读取类似

的内容
select id
    ,time
    ,name
from (
    select d.id
        ,d.time
        ,m.name
        ,m.start_time
        ,m.end_time
    from data as d LEFT OUTER JOIN mymap as m
        ON d.id = m.id
     ) x
where time>=start_time
        AND time<end_time

答案 1 :(得分:0)

您可以通过展平table2中的数据结构并使用UDF处理已连接的记录来解决此问题。

select
   id,
   time,
   nameFinderUDF(b.name_list, time) as name
from
   data a
LEFT OUTER JOIN
   (
   select
      id,
      collect_set(array(name,cast(start_time as string),cast(end_time as string))) as name_list
   from
      mymap 
   group by
      id
   ) b
ON (a.id=b.id)

使用UDF执行类似的操作:

public String evaluate(ArrayList<ArrayList<String>> name_list,Long time) {
    for (int i;i<name_list.length;i++) {
       if (time >= Long.parseLong(name_list[i][1]) && time <= Long.parseLong(name_list[i][2])) {
           return name_list[i][0]
    return null;
}

这种方法应该使合并1到1,但它可以创建一个相当大的数据结构重复多次。它比直接连接效率更高。