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

yhqotfr8  于 5个月前  发布在  其他
关注(0)|答案(3)|浏览(72)

我试图弄清楚如何在下面的表创建中查询我在哪里检查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;


当我这样做时,我得到:
语法错误:第1行:53:表达式“foo”.“usages”不是ROW类型
如果我在直接索引数组的地方进行查询,如下图所示,它可以工作。

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


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

scyqe7ek

scyqe7ek1#

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)

rn0zuynd

rn0zuynd2#

您可以通过将数组取消嵌套到行中,然后检查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

1u4esq0p

1u4esq0p3#

另一种模拟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

相关问题