在Athena中,如何查询结构数组中的结构成员?

时间:2019-09-12 17:38:00

标签: sql json presto amazon-athena

在尝试创建以下表格的情况下,我试图弄清楚如何查询usage的值:

CREATE EXTERNAL TABLE IF NOT EXISTS foo.test (
     `id` string,
     `foo` struct< usages:array< struct< usage:string,
     method_id:int,
     start_at:string,
     end_at:string,
     location:array<string> >>> 
) PARTITIONED BY (
         timestamp date 
) 
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES (
         'serialization.format' = '1' ) LOCATION 's3://foo.bar/' TBLPROPERTIES ('has_encrypted_data'='false');

我想要一个查询,例如:

SELECT * FROM "foo"."test" WHERE foo.usages.usage is null;

这样做,我得到:

  

SYNTAX_ERROR:第1行:53:表达式“ foo”。“用法”的类型不是ROW

如果我在查询中直接对数组进行索引,如下所示,那么它将起作用。

SELECT * FROM "foo"."test" WHERE foo.usages[1].usage is null;

尽管,我的总体目标是查询usages数组中的所有项目,并找到usages数组中至少一项具有成员usage为空的行。

2 个答案:

答案 0 :(得分:2)

雅典娜基于Presto。在Presto 318中,您可以使用any_match

SELECT * FROM "foo"."test"
WHERE any_match(foo.usages, element -> element.usage IS NULL);

我认为该功能在Athena中尚不可用,但是您可以使用reduce进行仿真。

SELECT * FROM "foo"."test"
WHERE reduce(
  foo.usages, -- array to reducing
  false, -- initial state
  (state, element) -> state OR element.usage IS NULL, -- combining function
  state -> state); -- output function (identity in this case)

答案 1 :(得分:1)

您可以通过将数组取消嵌套成行,然后检查其中的null值来实现。这将导致每个null值条目一行。

select * from test
CROSS JOIN UNNEST(foo.usages) AS t(i)
where i.usage is null

因此,如果您仅需要唯一的集合,则必须通过选择不同的集合来运行它。

select distinct id from test
CROSS JOIN UNNEST(foo.usages) AS t(i)
where i.usage is null