在雪花中展平嵌套的 JSON
Posted
技术标签:
【中文标题】在雪花中展平嵌套的 JSON【英文标题】:Flatten nested JSON in snowflake 【发布时间】: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 次迭代: 显然无法通过更多代码...需要更多详细信息。
【问题讨论】:
【参考方案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
【讨论】:
以上是关于在雪花中展平嵌套的 JSON的主要内容,如果未能解决你的问题,请参考以下文章