收集到配置单元中的Map

tvz2xvvm  于 2021-06-04  发布在  Hadoop
关注(0)|答案(5)|浏览(518)

我有一张Hive桌,比如

id  |  value
-------------
A      1
A      2
B      3
A      4
B      5

基本上,我想模仿python的 defaultdict(list) 并用 id 作为钥匙和 value 作为价值观。
查询:

select COLLECT_TO_A_MAP(id, value)
from table

输出:

{A:[1,2,4], B:[3,5]}

我试过用klout的 CollectUDAF() 但这似乎不会将值附加到数组中,它只会更新它们。有什么想法吗?
编辑:这里有一个更详细的描述,这样我可以避免引用我在配置单元文档中尝试的函数。假设我有一张table

num    |id    |value
____________________
1       A      1
1       A      2
1       B      3
2       A      4
2       B      5
2       B      6

我要找的是提供这个输出的udaf

num     |new_map
________________________
1       {A:[1,2], B:[3]}
2       {A:[4], B:[5,6]}

到此查询

select num
      ,COLLECT_TO_A_MAP(id, value) as new_map
from table
group by num

有一个解决方法来实现这一点。它可以通过使用klout进行模拟(参见上面引用的udaf) CollectUDAF() 在查询中,例如

add jar '~/brickhouse/target/brickhouse-0.6.0.jar'
create temporary function collect as 'brickhouse.udf.collect.CollectUDAF';

select num
       ,collect(id_array, value_array) as new_map
from (
      select collect_list(id) as id_array
            ,collect_list(value) as value_array
            ,num
      from table
      group by num
     ) A
group by num

但是,我不希望编写嵌套查询。
编辑#2
(正如我最初的问题中提到的)我已经试过使用klout的 CollectUDAF() ,即使在传递两个参数并创建Map的示例中也是如此。它的输出是(如果在我的第一次编辑中应用到数据集)

1    {A:2, B:3}
2    {A:4, B:6}

正如我在最初的问题中所说的,它不会将值收集到数组中,而只是收集最后一个值(或更新数组)。

kmynzznz

kmynzznz1#

您当前的查询在内部和外部查询中按num分组—您需要按num分组 id 在内部查询中完成您要做的事情。

f4t66c6m

f4t66c6m2#

在brickhouse中使用collect自定义项(http://github.com/klout/brickhouse )
这正是你需要的。如果使用一个参数,brickhouse的collect返回一个列表,如果使用两个参数,则返回一个map。

snvhrwxg

snvhrwxg3#

砖房里的收藏品(http://github.com/klout/brickhouse )我会带你去的。
关于您的评论编辑#2:
首先,将值收集到列表中,然后将k、v对收集到Map中:

select
    num,
    collectUDAF(id, values) as new_map
from
    (
    SELECT
        num,
        id,
        collect_set(value) as values
    FROM
        tbl
    GROUP BY
        num,
        id
    ) as sub
GROUP BY
    num

会回来的

num  | new_map
________________________
1      {A:[1,2], B:[3]}
2      {A:[4], B:[5,6]}
5t7ly7z5

5t7ly7z54#

https://github.com/klout/brickhouse/blob/master/src/main/java/brickhouse/udf/collect/collectudaf.java#l55
请参阅brickhouse udaf,当args num大于1时,将使用mapcollectudafecaluator。

add jar */brickhouse.jar ;
create temporary function collect  as 'brickhouse.udf.collect.CollectUDAF';
select 
collect(a,b)
from( select 1232123 a,21 b 
    union all select 123 a,23 b)a;

result:{1232123:21,123:23}
dw1jzc5e

dw1jzc5e5#

如果不关心值的显示顺序,可以使用hive附带的collect\u set()udaf。

SELECT id, collect_set(value) FROM table GROUP BY id;

这应该能解决你的问题。

相关问题