【问题标题】:Athena Unnesting mixed typesAthena Unnesting 混合类型
【发布时间】:2021-02-17 04:36:28
【问题描述】:

我通常会这样:

SELECT h.field1, rp.p.key1, rp.p.key2
FROM
  mytable h
  CROSS JOIN UNNEST(h.field2) rp (p)

但是,我现在正在考虑查询 AWS CloudTrail 数据。 在这里,我要取消嵌套的字段各不相同...

有时它是一个对象:

{"principal":{"dataLakePrincipalIdentifier":"arn:aws:iam::......

其他时候它包含一个围绕对象数组的包装对象

{"entries":[{"id":"0","principal":{"dataLakePrincipalIdentifier":"arn:aws:iam::.........

我目前能想到的解决这个问题的唯一方法是创建 2 个单独的查询;一个解包单例,另一个解包数组条目 - 然后将两个结果合并在一起。

如果有人知道更有效的方法,我将不胜感激?

【问题讨论】:

    标签: amazon-athena amazon-cloudtrail


    【解决方案1】:

    您应该能够通过检查对象内是否存在特定键来实现此目的,并执行以下操作:

    1. 如果键不存在,这绝对是一个类型的对象 (map(varchar, json)。将其转换为看起来像 map(varchar, array(json)。
    2. 如果密钥存在,请保持原样。

    假设,我们检查密钥 entries 的存在:

    with data as (
      select CAST(json_parse(your_json_string) AS MAP(VARCHAR, json )) as p
      from mydataset.mytable
    )
    
    select cast(json_extract(j, '$.principle') as map(varchar, integer)) as record from (
         select 
         if(
           cardinality(filter(map_keys(p), x -> x = 'entries')) = 1, 
           p,
           MAP(ARRAY['entries'], array[cast(array[p] as json)])
         ) as x from data2
    ), unnest(cast(x['entries'] as array(json))) as z(j)
    

    请注意这部分,特别是:

    if(
      cardinality(filter(map_keys(p), x -> x = 'entries')) = 1, 
      p,
      MAP(ARRAY['entries'], array[cast(array[p] as json)])
    )
    

    它完成了将单个对象转换为看起来像普通的 map(varchar, array(json)) 的工作,这使得一切看起来都相似。

    【讨论】:

    • 汗,抱歉回复晚了!但是谢谢你,这很棒,并且有很好的解释:)
    猜你喜欢
    • 2015-11-04
    • 2020-01-12
    • 2014-01-10
    • 2021-03-04
    • 2021-12-15
    • 2017-06-11
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多