[英]Parsing JSON in Snowflake
我正在尝试使用 Snowflake 中的后侧 function 解析 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"
},
或者如果您有很多行(似乎是航班),因此您需要为每个航班列此代码就是您所追求的
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"
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()));
我写这个是为了在任何雪花工作表中运行,不需要表格。 顶部的 function 仅允许将 JSON 作为多行字符串写入其下方的 SQL 语句中。 它除了代表一个包含您的 JSON 的字符串之外没有其他用途。
第 1 步是 PARSE_JSON,它将字符串转换为格式为 JSON object 的变体数据类型。
第 2 步是横向压平。 如果您对此进行 select 星号,它将返回许多列。 其中之一是“价值”。
第 3 步是提取您想要的属性,使用 single: 表示属性名称和点以从那里向下遍历节点(如果有的话)。
第 4 步是使用 double:: 表示法将属性转换为您想要的数据类型。 如果您要对列进行比较,尤其是在连接键中进行比较,这一点尤其重要。
请注意,JSON 有一个轻微的无效部分不允许它解析。 在顶层,数组有一个没有解析的属性。 我删除了它以允许解析。
可能接近您所寻求的是使用标准 SQL UNION 语句。
鉴于以下是正确的重新创建解决方案:
{
"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
;
这使您更接近您正在寻找的答案,并且似乎提供了一个更简单的解决方案。 您还可以根据每个目标 object 的 JSON object 属性来控制所需的行数。
增强这一点的建议是创建一个 function 可以检测每个嵌套元素的深度,并可能自动生成“n”个列的索引。
下面的库提供了一个名为“ExecuteAll”的方法,其中一个参数是“tags”,因此如果您提供一组标签和值,所有这些都将被解析和验证,并保留来自 Snowflake 的 sql 注入保护的功能.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.