首页 > 解决方案 > Hive 爆炸结构键数组:值:

问题描述

这是下面的 Hive 表

CREATE EXTERNAL TABLE IF NOT EXISTS SampleTable
(
USER_ID string,
DETAIL_DATA array<struct<key:string,value:string>>
)

这就是上表中的数据——

11111    [{"key":"client_status","value":"ACTIVE"},{"key":"name","value":"Jane Doe"}]

有什么方法可以使用 HiveQL 获得以下输出?

  **client_status**  |   **name**
  -------------------+----------------
         ACTIVE         Jane Doe  

我尝试使用explode()但我得到了这样的结果:

SELECT details
FROM sample_table
lateral view explode(DETAIL_DATA) exploded_table as details;


               **details** 
-------------------------------------------+
   {"key":"client_status","value":"ACTIVE"}        
 ------------------------------------------+
     {"key":"name","value":"Jane Doe"}              

标签: sqlarrayshivehiveqlexplode

解决方案


用于laterral view [outer] inline获取已提取的结构元素并使用条件聚合来获取与分组在单行中的某些键相对应的值,使用 group_by user_id。

演示:

with sample_table as (--This is your data example
select '11111' USER_ID,
array(named_struct('key','client_status','value','ACTIVE'),named_struct('key','name','value','Jane Doe')) DETAIL_DATA
)

SELECT max(case when e.key='name' then e.value end) as name, 
       max(case when e.key='client_status' then e.value end) as status
FROM sample_table
lateral view inline(DETAIL_DATA) e as key, value
group by USER_ID

结果:

    name    status  
------------------------
Jane Doe    ACTIVE

如果你能保证数组中结构的顺序(状态总是先出现),你可以直接处理嵌套元素

SELECT detail_data[0].value as client_status,
       detail_data[1].value as name
 from sample_table 

另一种方法,如果您不知道数组中的顺序,但数组的大小=2,则不带爆炸的 CASE 表达式将提供更好的性能:

SELECT case when DETAIL_DATA[0].key='name' then DETAIL_DATA[0].value else  DETAIL_DATA[1].value end as name, 
       case when DETAIL_DATA[0].key='client_status' then DETAIL_DATA[0].value else  DETAIL_DATA[1].value end as status
FROM sample_table

推荐阅读