【问题标题】:How to create an empty array of struct in hive?如何在 hive 中创建一个空的结构数组?
【发布时间】:2019-09-24 18:26:18
【问题描述】:

我在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;

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

如何更改它以返回 array&lt;struct&lt;name: string, jobslots:int&gt;&gt; 类型的空数组,以便 Hive's size() 函数在此数组上返回 0?

【问题讨论】:

  • 试试array(named_struct('name', NULL, 'jobslot', NULL))而不是空数组,或者只是NULL也可以。
  • 是的,null 可以工作,但 null 的 size() 返回 -1。我想要一个大小为 0 的空数组
  • size 的行为很奇怪。正如 OP 提到的select size(null) 返回-1select size(array()) 返回1
  • 请检查我的答案,我演示了如何生成空数组

标签: sql arrays struct hive hiveql


【解决方案1】:

您可以使用collect_listcolect_set 来收集从连接中获取的结构数组,如果连接条件为假,那么 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

结果:

a.id    array_size_zero
2       true

如果您将第一个子查询中的 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  

结果:

id  my_array
1   [{"name":null,"value":null}]
2   []

如果我尝试 UNION ALL 不同类型的空结构数组会发生什么,例如 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

例外:

编译语句时出错:FAILED: SemanticException Schema of 联合的两边应该匹配:列 my_array 是类型 第一个表上的数组和类型 array 在第二个表上。不能告诉 空 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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    相关资源
    最近更新 更多