Mysql 查询AWS Athena中第一个非空值的动态JSON字段

Mysql 查询AWS Athena中第一个非空值的动态JSON字段,mysql,amazon-s3,presto,amazon-athena,Mysql,Amazon S3,Presto,Amazon Athena,我将事件数据存储在S3中,并希望使用Athena查询数据。其中一个字段是动态JSON字段,我不知道该字段的名称。因此,我需要查询JSON中的键,然后使用这些键来查询该字段的第一个非空值。下面是存储在S3中的数据示例 { timestamp: 1558475434, request_id: "83e21b28-7c12-11e9-8f9e-2a86e4085a59", user_id: "example_user_id_1", traits: { this: "is", dynam

我将事件数据存储在S3中,并希望使用Athena查询数据。其中一个字段是动态JSON字段,我不知道该字段的名称。因此,我需要查询JSON中的键,然后使用这些键来查询该字段的第一个非空值。下面是存储在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)中提取键,并使用这些键为每个字段获取第一个非空值

最接近的方法是使用minu-by对值进行采样,但这不允许我在不返回null值的情况下添加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
选择DISTINCT trait,min_by(json_extract(traits,concat(“$”,cast(trait AS varchar))),received_at)作为值
从桌子上
交叉连接UNNEST(regexp_extract_all(traits),“([^”]+)”\s*:\s*(“[^”]+“[^,{}]+)”,1))作为t(trait)
其中json_extract(traits,concat(“$”,cast(trait AS varchar)))不为NULL或json_size(traits,concat(“$”,cast(trait AS varchar)))0
按特征分组

我不清楚您期望的结果是什么,以及“第一个非空值”是什么意思。在您的示例中,您同时拥有字符串和数组值,并且它们都不为null。如果您提供更多示例和预期输出,这将非常有用

作为解决方案的第一步,这里有一种从
traits
中过滤空值的方法:

如果将
traits
列的类型设置为
map
,则应该能够执行以下操作:

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

组合来实现的。您找到了解决方案吗?您能给出一个示例,说明您预期的结果吗?“每个字段的第一个非空值”并不完全清楚,值是字符串和数组,示例中没有一个为空。你的意思是,当一个值是一个数组时,它将获取第一个非null元素,还是仅获取非null值而不考虑类型?