如何解决在JSON列中解压缩所有数组SQL Server 2019
id | json_col
在表格上
id=1
json_col ={"names":["John","Peter"],"ages":["31","40"]}
names
和ages
的长度始终相等,但ID之间可能有所不同(大小至少为1,但没有上限)。
我们如何获得“爆炸式”表格-每个“名称”,“年龄”都带有一行的表格,例如
id | names | ages
---+-------+------
1 | John | 31
1 | Peter | 41
2 | Jim | 17
3 | Foo | 2
.
.
我尝试了OPEnjsON
和CROSS APPLY,但是以下给出了names
和ages
的任意组合,这是不正确的,因此我之后需要进行大量过滤
SELECT *
FROM Schema.table
CROSS APPLY OPEnjsON(Schema.table,'$.names')
CROSS APPLY OPEnjsON(Schema.table,'$.ages')
解决方法
可以使用条件聚合以及应用CROSS APPLY
:
SELECT id,MAX(CASE WHEN RowKey = 'names' THEN value END) AS names,MAX(CASE WHEN RowKey = 'ages' THEN value END) AS ages
FROM
(
SELECT id,Q0.[value] AS RowArray,Q0.[key] AS RowKey
FROM tab
CROSS APPLY OPENJSON(JsonCol) AS Q0
) r
CROSS APPLY OPENJSON(r.RowArray) v
GROUP BY id,v.[key]
ORDER BY id,v.[key]
id | names | ages
---+-------+------
1 | John | 31
1 | Peter | 41
2 | Jim | 17
3 | Foo | 2
OPENJSON
的第一个参数将是JSON列值,而不是表本身
这是我的建议
DECLARE @tbl TABLE(id INT,json_col NVARCHAR(MAX));
INSERT INTO @tbl VALUES(1,N'{"names":["John","Peter"],"ages":["31","40"]}'),(2,N'{"names":["Jim"],"ages":["17"]}');
SELECT t.id,B.[key] As ValueIndex,B.[value] AS PersonNam,JSON_VALUE(A.ages,CONCAT('$[',B.[key],']')) AS PersonAge
FROM @tbl t
CROSS APPLY OPENJSON(t.json_col)
WITH(names NVARCHAR(MAX) AS JSON,ages NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.names) B;
简而言之:
- 我们将
OPENJSON
与WITH
子句一起使用,将names
和ages
读入新的json变量中。 - 我们再使用
OPENJSON
来“分解”名称数组 - 由于
key
是值在数组中的位置,因此我们可以使用JSON_VALUE()
通过其位置读取相应的年龄值。
一个一般性说明:如果此JSON受您控制,则应将其更改为以实体为中心的方法(对象数组)。这种与位置有关的存储可能很麻烦……尝试类似
{"persons":[{"name":"John","age":"31"},{"name":"Peter","age":"40"}]}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。