根据其他表筛选数组

时间:2017-07-03 16:12:11

标签: sql hive hiveql

我试图过滤数组中的值。应保留哪些值的信息在另一个表格中。

table_a                        table_b
___________________            ___________
| id | values     |            | keyword |
-------------------            -----------
| 1  | [a, b, c]  |            |    b    |
| 2  | [d, e, f]  |            |    e    |
| 3  | [a, g]     |            |    f    |
-------------------            -----------

我期待以下输出:

output
________________________
| id | filtered_values | 
------------------------
| 1  | [b]             | 
| 2  | [e, f]          |
| 3  | []              |
------------------------

目前,我正在使用以下查询:

SELECT
  id,
  array_intersect(ta.values, tb.filter_keywords) AS filtered_values -- brickhouse UDF
FROM
  table_a ta
CROSS JOIN (
  SELECT
    collect_set(keyword) as filter_keywords
  FROM (
    SELECT
      "dummy" as grouping_dummy,
      keyword
    FROM
      table_b
  ) tmp
  GROUP BY
    grouping_dummy
)

table_a有几百万行,table_b包含少于1000行。 我猜交叉连接是瓶颈,因为它只使用一个减速器。

有没有办法优化此查询?

谢谢!

1 个答案:

答案 0 :(得分:0)

我有一个不同的假设。

需要使用reducer来生成filter_keywords,而不是CROSS JOIN,这是地图边操作。
所以这里没问题。

我的猜测是性能损失来自于array_intersect使用1000个元素的数组,因此解决方案将避免它。

P.S。
不需要grouping_dummy 您无需使用GROUP BY即可使用聚合函数。

select      a.id
           ,collect_list (case when b.keyword is not null then a.val end)  as vals


from       (select  a.id
                   ,e.val

            from    table_a a

                        lateral view outer 

                            explode (a.vals) e as val
            ) a

            left join   table_b b

            on          b.keyword   =
                        a.val

group by    a.id
+----+-----------+
| id |   vals    |
+----+-----------+
|  1 | ["b"]     |
|  2 | ["e","f"] |
|  3 | []        |
+----+-----------+