我将事件数据存储在S3中,并希望使用Athena来查询数据。字段之一是动态JSON字段,我不知道其字段名称。因此,我需要查询JSON中的键,然后使用这些键来查询该字段的第一个非null值。以下是S3中存储的数据的示例。
{
timestamp: 1558475434,
request_id: "83e21b28-7c12-11e9-8f9e-2a86e4085a59",
user_id: "example_user_id_1",
traits: {
this: "is",
dynamic: "json",
as: ["defined","by","the", "client"]
}
}
因此,我需要一个查询以从traits列(存储为JSON)中提取键,并使用这些键获取每个字段的第一个非空值。
我能找到的最接近的样本是使用min_by采样值,但这不允许我添加where子句而不返回空值。我将需要使用presto的“ first_value”选项,但是我无法使用它来处理从动态JSON字段提取的JSON密钥。
SELECT DISTINCT trait, min_by(json_extract(traits, concat('$.', cast(trait AS varchar))), received_at) AS value
FROM TABLE
CROSS JOIN UNNEST(regexp_extract_all(traits,'"([^"]+)"\s*:\s*("[^"]+"|[^,{}]+)', 1)) AS t(trait)
WHERE json_extract(traits, concat('$.', cast(trait AS varchar))) IS NOT NULL OR json_size(traits, concat('$.', cast(trait AS varchar))) <> 0
GROUP BY trait
答案 0 :(得分:0)
我不清楚您期望得到的结果以及“第一个非空值”的含义。在您的示例中,您同时具有字符串和数组值,而且都不为空。如果您提供更多示例以及预期的输出,将会很有帮助。
作为解决方案的第一步,这是一种从traits
中过滤出空值的方法:
如果将traits
列的类型设置为map<string,string>
,则应该可以执行以下操作:
SELECT
request_id,
MAP_AGG(ARRAY_AGG(trait_key), ARRAY_AGG(trait_value)) AS trait
FROM (
SELECT
request_id,
trait_key,
trait_value
FROM some_table CROSS JOIN UNNEST (trait) AS t (trait_key, trait_value)
WHERE trait_value IS NOT NULL
)
但是,如果您还想过滤数组值并挑选出第一个非空值,那就变得更加复杂了。可以结合使用强制转换为JSON,filter
函数和COALESCE
来实现。