我正在尝试找出如何查询在创建以下表的情况下检查
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
为空的任何行。
Athena 基于 Presto。在 Presto 318 中您可以使用
any_match
:
SELECT * FROM "foo"."test"
WHERE any_match(foo.usages, element -> element.usage IS NULL);
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)
您可以通过将数组取消嵌套到行中来实现此目的,然后检查这些行中的
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
模拟
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