【问题标题】:Parsing JSON in Snowflake在雪花中解析 JSON
【发布时间】:2020-07-29 02:50:50
【问题描述】:

我正在尝试使用 Snowflake 中的后侧函数解析 Snowflake 中的以下嵌套 JSON,但我希望“GoalTime”中的每个嵌套列都显示为一列。例如,

GoalTime_InDoorOpen         
2020-03-26T12:58:00-04:00   

GoalTime_InLastOff
null

GoalTime_OutStartBoarding
2020-03-27T14:00:00-04:00  
"GoalTime": [
    {
      "GoalName": "GoalTime_InDoorOpen",
      "GoalTime": "2020-03-26T12:58:00-04:00"
    },
    {
      "GoalName": "GoalTime_InLastOff"
    },
    {
      "GoalName": "GoalTime_InReadyToTow"
    },
    {
      "GoalName": "GoalTime_OutTowAtGate"
    },
    {
      "GoalName": "GoalTime_OutStartBoarding",
      "GoalTime": "2020-03-27T14:00:00-04:00"
    },

【问题讨论】:

    标签: sql json azure snowflake-cloud-data-platform


    【解决方案1】:

    或者如果您有很多行(似乎是航班),因此您需要在每个航班上列此代码是您所追求的

    with data as (
    select flight_code, parse_json(json) as json from values ('nz101','{GoalTime:[{"GoalName": "GoalA", "GoalTime": "2020-03-26T12:58:00-04:00"}, {"GoalName": "GoalB"}]}'),
                                                     ('nz201','{GoalTime:[{"GoalName": "GoalA"}, {"GoalName": "GoalB", "GoalTime": "2020-03-26T12:58:00-02:00"}]}') 
                                                     j(flight_code, json)
    ), unrolled as (
    select d.flight_code, f.value:GoalName as goal_name, f.value:GoalTime as goal_time
    from data d,
    lateral flatten (input => json:GoalTime) f
    )
    select * 
    from unrolled
        pivot(min(goal_time) for goal_name in ('GoalA', 'GoalB'))
    order by flight_code;
    

    它给出了结果:

    FLIGHT_CODE 'GoalA'                       'GoalB'
    nz101       "2020-03-26T12:58:00-04:00"   null
    nz201       null                          "2020-03-26T12:58:00-02:00"
    

    【讨论】:

      【解决方案2】:
      create or replace function JSON_STRING()
      returns string
      language javascript
      as
      $$
      return `
      [
        {
              "GoalName": "GoalTime_InDoorOpen",
              "GoalTime": "2020-03-26T12:58:00-04:00"
          },
          {
              "GoalName": "GoalTime_InLastOff"
          },
          {
              "GoalName": "GoalTime_InReadyToTow"
          },
          {
              "GoalName": "GoalTime_OutTowAtGate"
          },
          {
              "GoalName": "GoalTime_OutStartBoarding",
              "GoalTime": "2020-03-27T14:00:00-04:00"
          }
      ]
      `;
      $$;
      
      select value:GoalName::string as GoalName, value:GoalTime::timestamp as GoalTime
      from lateral flatten(input => parse_json(JSON_STRING()));
      
      -- See how the lateral flatten combination works on a JSON variant:
      select * from lateral flatten(input => parse_json(JSON_STRING()));
      

      我写这个是为了在任何 Snowflake 工作表中运行,不需要表格。上面的函数只是允许将 JSON 作为多行字符串写入它下面的 SQL 语句中。除了表示保存 JSON 的字符串之外,它没有其他用途。

      第 1 步是 PARSE_JSON,它将字符串转换为格式化为 JSON 对象的变体数据类型。

      第 2 步是横向压平。如果您对此进行选择星,它将返回许多列。其中之一是“价值”。

      第 3 步是使用单 : 表示法提取您想要的属性名称和点以从那里遍历节点(如果有的话)。

      第 4 步是使用双 :: 表示法将属性转换为您想要的数据类型。如果您要对列进行比较,尤其是在连接键中进行比较,这一点尤其重要。

      请注意,JSON 中有一个轻微的无效部分不允许它解析。在顶层,数组有一个没有解析的属性。我删除了它以允许解析。

      【讨论】:

        【解决方案3】:

        使用标准 SQL UNION 语句可能接近您所寻求的。

        鉴于以下情况正确,重新创建解决方案:

        • 创建了一个表“JSON_GOALS”,其中一列用于原始 JSON,称为 GOALS_RAW
        • 您已将 JSON 数据作为原始 JSON 加载到表中,具有兼容的 JSON 对象数组语法和父级 GoalTimeGroup,例如:{[{}]},所以
        {
            "GoalTimeGroup": [{
                    "GoalName": "GoalTime_InDoorOpen",
                    "GoalTime": "2020-03-26T12:58:00-04:00"
                },
                {
                    "GoalName": "GoalTime_InLastOff"
                },
                {
                    "GoalName": "GoalTime_InReadyToTow"
                },
                {
                    "GoalName": "GoalTime_OutTowAtGate"
                },
                {
                    "GoalName": "GoalTime_OutStartBoarding",
                    "GoalTime": "2020-03-27T14:00:00-04:00"
                }
            ]
        }
        

        这样做允许您使用以下语法在 Snowflake 中编写相当标准的 JSON 检索:

        SELECT GOALS_RAW:GoalTimeGroup[0].GoalName, GOALS_RAW:GoalTimeGroup[1].GoalName, GOALS_RAW:GoalTimeGroup[2].GoalName
        FROM JSON_GOALS 
        UNION
        SELECT GOALS_RAW:GoalTimeGroup[0].GoalTime, GOALS_RAW:GoalTimeGroup[1].GoalTime, GOALS_RAW:GoalTimeGroup[2].GoalName
        FROM JSON_GOALS 
        ;
        

        这使您更接近您正在寻找的答案,并且似乎提供了一个更简单的解决方案。您还可以根据每个 GOAL 对象的 JSON 对象属性来控制所需的行数。

        增强这一点的建议是创建一个函数,该函数可以检测每个嵌套元素的深度,并可能自动为“n”个列生成索引。

        【讨论】:

          【解决方案4】:

          下面的库提供了一个名为“ExecuteAll”的方法,其中一个参数是“tags”,所以如果你提供一个标签和值的数组,它们都会被解析和验证,并保留sql注入的特性防止雪花。

          snowflake-multisql

          【讨论】:

            猜你喜欢
            • 2021-04-11
            • 1970-01-01
            • 2022-07-04
            • 2021-09-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-08-09
            相关资源
            最近更新 更多