【问题标题】:Flatten nested JSON in snowflake在雪花中展平嵌套的 JSON
【发布时间】:2020-09-16 13:02:35
【问题描述】:

这是 JSON 的一个示例(它可以是更多或更少的类型和/或值。 我想结束(顺序不重要):

国家,IC 国家,ES 国家,SE 国家,GB 国家,美国 分类、电影聊天

JSON

{
  "list": [
    {
      "element": {
        "comparison": "anyOf",
        "logical": "and",
        "type": "Countries",
        "value": {
          "list": [
            {
              "element": "IC"
            },
            {
              "element": "ES"
            },
            {
              "element": "SE"
            },
            {
              "element": "GB"
            },
            {
              "element": "US"
            }
          ]
        }
      }
    },
    {
      "element": {
        "comparison": "anyOf",
        "logical": "and",
        "type": "Categories",
        "value": {
          "list": [
            {
              "element": "film-chat"
            }
          ]
        }
      }
    }
  ]
}

到目前为止我已经尝试过,可能是第 17 次迭代: 显然无法通过更多代码...需要更多详细信息。

【问题讨论】:

    标签: snowflake-cloud-data-platform


    【解决方案1】:

    不久前,我实际上围绕它写了一篇文档:

    https://community.snowflake.com/s/article/Dynamically-extract-multi-level-JSON-object-using-lateral-flatten

    它允许动态提取所有嵌套级别最高为第 4 级的字段(您可以随时添加更多),然后您可以使用常规选择按您需要的方式对它们进行排序。

    【讨论】:

    • 是的,目前正在这样做,但我没有得到第 5 级值的密钥。
    【解决方案2】:

    您是否使用FLATTEN() 记录在https://docs.snowflake.com/en/sql-reference/functions/flatten.html

    我们需要做更多的工作,但您最终可能会得到以下结果:

    with tbl as (select parse_json($1) json from values ('{"list":[{"element":{"comparison":"anyOf","logical":"and","type":"Countries","value":{"list":[{"element":"IC"},{"element":"ES"},{"element":"SE"},{"element":"GB"},{"element":"US"}]}}},{"element":{"comparison":"anyOf","logical":"and","type":"Categories","value":{"list":[{"element":"film-chat"}]}}}]}'))
    select *
    from tbl,
      lateral flatten(json:list) list_l1 ,
      lateral flatten(list_l1.value:element) element_l1,
      lateral flatten(element_l1.value:list, OUTER => TRUE) list_l2 ,
      lateral flatten(list_l2.value:element, OUTER => TRUE) element_l2
    

    【讨论】:

    • 看到了,但没能成功。会再试一次。
    【解决方案3】:

    如果我们假设我们有一个如下定义(和填充)的表:

    CREATE OR REPLACE TEMPORARY TABLE MY_TABLE (
      MY_DICT  VARIANT
    )
    AS
      SELECT PARSE_JSON($1) AS MY_DICT
        FROM VALUES ($$
      {
        "list": [
          {
            "element": {
              "comparison": "anyOf",
              "logical": "and",
              "type": "Countries",
              "value": {
                "list": [
                  {
                    "element": "IC"
                  },
                  {
                    "element": "ES"
                  },
                  {
                    "element": "SE"
                  },
                  {
                    "element": "GB"
                  },
                  {
                    "element": "US"
                  }
                ]
              }
            }
          },
          {
            "element": {
              "comparison": "anyOf",
              "logical": "and",
              "type": "Categories",
              "value": {
                "list": [
                  {
                    "element": "film-chat"
                  }
                ]
              }
            }
          }
        ]
      }
      $$)
    ;
    

    那么我们可以使用这个查询来返回你指定的信息:

    SELECT LISTAGG(F1.VALUE:"element":"type"::VARCHAR || ', ' || F2.VALUE:"element"::VARCHAR, ' ')
      FROM MY_TABLE
          ,LATERAL FLATTEN(MY_TABLE.MY_DICT:"list") F1
          ,LATERAL FLATTEN(F1.VALUE:"element":"value":"list") F2
    ;
    

    编辑(基于您关于想要行的评论,而不是连接的字符串列):

    只需去掉LISTAGG(),如下:

    SELECT F1.VALUE:"element":"type"::VARCHAR || ', ' || F2.VALUE:"element"::VARCHAR AS TYPE_ELEMENT
      FROM MY_TABLE
          ,LATERAL FLATTEN(MY_TABLE.MY_DICT:"list") F1
          ,LATERAL FLATTEN(F1.VALUE:"element":"value":"list") F2
    ;
    

    如果你想要一个简单的结果集,有 2 列(你的规范中不清楚),那么你可以使用这个:

    SELECT F1.VALUE:"element":"type"::VARCHAR AS TYPE
          ,F2.VALUE:"element"::VARCHAR AS ELEMENT
      FROM MY_TABLE
          ,LATERAL FLATTEN(MY_TABLE.MY_DICT:"list") F1
          ,LATERAL FLATTEN(F1.VALUE:"element":"value":"list") F2
    ;
    

    【讨论】:

    • 这行得通。现在它在一列中。需要将该列变为行...
    • 但是当无限制时我得到“String '(LISTAGG result)' is too long and will be truncated”
    【解决方案4】:
    select
        id,
        f1.value:element:type::string type,
        f2.value:element::string element
    from
        table,
        lateral flatten(input => table.json, path => 'list') f1,
        lateral flatten(input => f1.value:element:value:list) f2
    

    【讨论】:

      猜你喜欢
      • 2022-07-06
      • 2021-08-13
      • 2021-07-23
      • 2022-01-22
      • 2021-07-16
      • 2021-12-18
      • 2021-06-25
      • 2022-01-21
      • 2020-09-16
      相关资源
      最近更新 更多