apacheimpala:project map< string,string>键作为单独的列

mpgws1up  于 2021-05-27  发布在  Hadoop
关注(0)|答案(2)|浏览(264)

在impala中,是否可以将Map中的Map键投影为结果集中的实际列?我正在接收一个数据集,其中我们无法提前知道所有可能的属性,因此我们使用map列来获得最大的灵活性。但是,在查询时,我们仍然希望将这些属性作为它们自己的列拉出。
下面的简化示例有几个唯一的键(实际上,我们的数据集中有数百个键)
架构:

Column  |  Type
-------------------
name    |  STRING
props   |  MAP<string, string>

原始表:

Name    |  Props
-----------------
Bob     |  {"age": "39", "fav_color": "green"}
Alice   |  {"fav_animal": "dog", "fav_color": "blue"}

期望结果:

name    |  age  |  fav_color    |  fav_animal
----------------------------------------------
Bob     |  39   |  green        |  NULL
Alice   |  NULL |  blue         |  dog

我可以通过以下方式以行为导向获得所有结果
选择name,props.key,props.value from table,table.props props;
但是,我还没有弄清楚如何将这些键从map type列变成它们自己的列。在 Impala 有没有有效的方法?
(我很乐意编写一个自定义的udf,但是impala udf不能接受像map这样的复杂类型:(很遗憾)

xwmevbvl

xwmevbvl1#

找到了一个潜在的解决方案,但是对于大量的属性来说它是非常缓慢和麻烦的。下面的查询将两个属性提取到单独的列中。
如果可能的话,更愿意找到一个更有效、更简单的解决方案。

select 
    a1.name,
    a1.age,
    a2.fav_animal
from 
(   select
        t1.name,
        case t1.attr
            when 'age' then t1.value
        end `age` 
    from (
        select
            name,
            a.key attr,
            a.value value
        from
            mytable, mytable.props a
        where 
            a.key = 'age'
    ) t1
) 
a1 left join 
(   select
        t2.name,
        case t2.attr
            when 'fav_animal' then t2.value
        end `fav_animal` 
    from (
        select
            name,
            a.key attr,
            a.value value
        from
            mytable, mytable.props a
        where 
            a.key = 'fav_animal'
    ) t2
) 
a2 on a1.name = a2.name
limit 10;
sirbozc5

sirbozc52#

我可以使用impala(cdh5.13)中的struct数据类型来实现这一点。下面是我遵循的一系列步骤。注意,impala只支持parquet格式的struct数据类型。因此,我使用hive创建表并将数据加载到其中,然后使用impala查询相同的表。

Hive

create table raw_table_parq (
 name string,
 details struct < age: STRING, fav_color: STRING, fav_animal: STRING >
)
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY '$'
STORED AS PARQUET;

testfile.csv
'Bob',39$'green'$''
'Alice',''$'blue'$'dog'

首先创建一个基于文本文件的暂存表,将csv加载到暂存表中,然后使用“insert into”将表加载到parquet表中。一旦数据加载到所需的表中,在impala中使用下面的查询:

[quickstart.cloudera:21000] > select name, details.age, details.fav_color, details.fav_animal from test.raw_table_parq;
Query submitted at: 2019-12-30 06:31:09 (Coordinator: http://quickstart.cloudera:25000)
Query progress can be monitored at: http://quickstart.cloudera:25000/query_plan?query_id=2f436ff7e3301734:f6f0a75700000000
+---------+-------------+-------------------+--------------------+
| name    | details.age | details.fav_color | details.fav_animal |
+---------+-------------+-------------------+--------------------+
| 'Bob'   | 39          | 'green'           | ''                 |
| 'Alice' | ''          | 'blue'            | 'dog'              |
+---------+-------------+-------------------+--------------------+
Fetched 2 row(s) in 0.13s

希望这有帮助。

相关问题