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

问题描述 投票:0回答:3

我正在尝试找出如何查询在创建以下表的情况下检查

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”。“usages”不是 ROW 类型

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

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

我的总体目标是查询

usages
数组中的所有项目,并找到
usages
数组中至少有一个项目的成员
usage
为空的任何行。

sql json presto amazon-athena
3个回答
8
投票

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)

2
投票

您可以通过将数组取消嵌套到行中来实现此目的,然后检查这些行中的

null
值。这将导致每个
null
值条目占一行。

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

因此,如果您只需要唯一的集合,则必须通过

SELECT DISTINCT
来运行它。

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

2
投票

模拟

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
© www.soinside.com 2019 - 2024. All rights reserved.