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

In Athena how do I query a member of a struct in an array in a struct?

我正在尝试找出如何查询我正在检查 usage 的值的位置,给出以下 table 创建:

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: line 1:53: Expression "foo"."usages" is not of type ROW

如果我在直接索引数组的位置进行查询,如下所示,它会起作用。

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

不过,我的总体目标是查询 usages 数组中的所有项目,并找到任何行,其中 usages 数组中至少有一个项目具有成员 usage空。

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

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

因此,如果您只需要唯一集,则必须 运行 通过 select 不同。

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

Athena 基于 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)

另一种模拟 any_match(<array>, <function>) 的方法是 cardinality(filter(<array>, <function>)) > 0.

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

变为:

SELECT * FROM "foo"."test"
WHERE cardinality(filter(foo.usages, element -> element.usage IS NULL)) > 0