如何在 hive 中创建一个空的结构数组?

Joh*_*oha 11 sql arrays struct hive hiveql

我有一个视图Hive 1.1.0,基于条件,它应该返回一个空数组或一个数组struct<name: string, jobslots: int>

这是我的代码:

select
      case when <condition> 
             then array()
           else array(struct(t1.name, t1.jobslots))
       end
from table t1;
Run Code Online (Sandbox Code Playgroud)

这里的问题是,空数组array()的类型是array<string>。因此,当我尝试将其插入表中时,它会引发错误。

如何更改它以返回类型为空的数组,array<struct<name: string, jobslots:int>>以便Hive's size()函数在该数组上返回 0?

lef*_*oin 0

您可以使用collect_listcolect_set收集从连接中获取的结构数组来完成此操作,并且连接条件为 false,则collect_list 将生成一个空结构数组。

此查询返回大小为 0 的数组:

select a.id, size(collect_list(b.str))=0 array_size_zero
from
(select 2 id ) a
  left join (select 1 as id, named_struct('name',null,'value',null) as str) b
            on a.id=b.id
group by a.id
Run Code Online (Sandbox Code Playgroud)

结果:

a.id    array_size_zero
2       true
Run Code Online (Sandbox Code Playgroud)

如果您更改第一个子查询 a 中的 id 以与 b 连接,它将返回包含 1 个元素的数组。而且这些结果是同一类型的,您可以使用 union all 轻松检查。

检查结果是同一类型:

select a.id, collect_list(b.str) my_array
from
(select 1 id ) a
  left join (select 1 as id, named_struct('name',null,'value',null) as str) b
            on a.id=b.id
group by a.id

union all

select a.id, collect_list(b.str) my_array
from
(select 2 id ) a
  left join (select 1 as id, named_struct('name',null,'value',null) as str) b
            on a.id=b.id
group by a.id  
Run Code Online (Sandbox Code Playgroud)

结果:

id  my_array
1   [{"name":null,"value":null}]
2   []
Run Code Online (Sandbox Code Playgroud)

如果我尝试将不同类型的结构的所有空数组联合起来,例如 array(),会发生什么:

select 1 id, array() my_array

union all

select a.id, collect_list(b.str) my_array
from
(select 2 id ) a
  left join (select 1 as id, named_struct('name',null,'value',null) as str) b
            on a.id=b.id
group by a.id
Run Code Online (Sandbox Code Playgroud)

例外:

编译语句时出错:FAILED:SemanticException 联合两侧的架构应匹配:第一个表上的列 my_array 为 array 类型,第二个表上的列 my_array 为 array<structname:void,value:void> 类型。无法判断空 AST 的位置。

这表明第一个查询确实返回了空的结构数组。您可以轻松地在查询中执行类似的连接。

如何在带条件的查询中使用它?演示:

select a.id, case when true --Put your condition here instead of dummy <true> 
                     then collect_list(a.str) --not empty
                  else collect_list(b.str) --this one is empty array of the same type
              end as my_array
from
(select 2 id, named_struct('name',null,'value',null) str) a
  left join (select 1 as id, named_struct('name',null,'value',null) as str) b
            on FALSE
group by a.id
Run Code Online (Sandbox Code Playgroud)

CASE 表达式非常满意,并且不会引发有关不兼容类型的异常