在sql server中将行/表记录转换为json文档
Posted
技术标签:
【中文标题】在sql server中将行/表记录转换为json文档【英文标题】:convert rows/table records to json document in sql server 【发布时间】:2019-06-22 07:38:08 【问题描述】:以下是作为输入的样本数据
if object_id('tempdb.dbo.#store_data') is not null
drop table #store_data
create table #store_data ([key] nvarchar(max),[value] nvarchar(max),storeid varchar(100)
)
INSERT INTO #store_data VALUES ('sid','1','1')
INSERT INTO #store_data VALUES ('bid','3','1');
INSERT INTO #store_data VALUES ('time','2019-01-01','1');
INSERT INTO #store_data VALUES ('que','apple','1');
INSERT INTO #store_data VALUES ('sid','2','2');
INSERT INTO #store_data VALUES ('bid','5','2');
INSERT INTO #store_data VALUES ('hrs','6','2');
INSERT INTO #store_data VALUES ('dat','pine','2');
select * from #store_data
以下是需要的结果
[
"sid"="1",
"bid"="3",
"time"="2019-01-01"
"que"="apple",
"sid"="2",
"bid"="5",
"hrs"="6",
"dat"="pine"
]
以下是我尝试过的查询
select [key],[value] from #store_data for json path
没有达到预期的效果。
【问题讨论】:
您应该知道,没有隐式排序顺序! 如果没有最外层的ORDER BY
,这可以工作数百次,通过所有内部测试,但会返回生产中的垃圾。如果bid=3
出现在第一个或第二个 JSON 对象中,那就不是随机的了。
我已经更新了我的答案@Shnugo...由 PSK 给出...我使用循环来获取结果集...但我觉得还有另一种方法可以按相同顺序检索跨度>
是否循环:SQL-Server 的排序方式与您插入数据的方式不同。任何没有最外层ORDER BY
的SELECT
都可以以任何随机排序顺序返回。如果要保持排序顺序,最简单的方法是添加IDENTITY
列。
【参考方案1】:
请注意,你不能直接查询,你必须先PIVOT
storeid
。
您可以尝试如下查询。
select sid, bid, time,que, hrs,dat
from #store_data src
pivot
(
MAX([value])
for [key] in (sid, bid, time,que, hrs,dat)
) piv
for json auto
完整示例
if object_id('tempdb.dbo.#store_data') is not null
drop table #store_data
create table #store_data ([key] nvarchar(max),[value] nvarchar(max),storeid varchar(100))
INSERT INTO #store_data VALUES ('sid','1','1')
INSERT INTO #store_data VALUES ('bid','3','1');
INSERT INTO #store_data VALUES ('time','2019-01-01','1');
INSERT INTO #store_data VALUES ('que','apple','1');
INSERT INTO #store_data VALUES ('sid','2','2');
INSERT INTO #store_data VALUES ('bid','5','2');
INSERT INTO #store_data VALUES ('hrs','6','2');
INSERT INTO #store_data VALUES ('dat','pine','2');
select sid, bid, time,que, hrs,dat
from #store_data src
pivot
(
MAX([value])
for [key] in (sid, bid, time,que, hrs,dat)
) piv
for json auto
输出:
[
"sid": "1",
"bid": "3",
"time": "2019-01-01",
"que": "apple"
,
"sid": "2",
"bid": "5",
"hrs": "6",
"dat": "pine"
]
在线演示:
Here
编辑:
PIVOT
自动在stroeid
ASC
上订购,无需指定任何顺序。如果您想将其更改为不同的顺序,比如说DESC stroeid
,在这种情况下,您可以按以下方式更改查询。
select sid, bid, time,que, hrs,dat
from #store_data src
pivot
(
MAX([value])
for [key] in (sid, bid, time,que, hrs,dat)
) piv
order by storeid desc
for json auto
【讨论】:
嗨,虽然这可能是正确的方法,但我们不能厌倦指出这一事实,即 没有隐式排序顺序! 没有最外层的ORDER BY
this可以工作数百次,通过所有内部测试,但会在生产中返回垃圾。如果bid=3
出现在第一个或第二个 JSON 对象中,那就不是随机的了。
嗨@Shnugo,我不确定我是否明白这一点。你的评论超出了我的认知。您能否再解释一下或一些可以重现场景的示例数据
好吧,我有点太快了,因为我没有第一眼看到storeid
,它包含在SELECT *
中。连同这些信息,对象将获得正确的值(作为组)。如果没有这个 storeid
作为最终 JSON 的一部分,它仍然成立,您无法保证哪个 JSON 对象将首先出现,哪个将出现在第二个。但这并不是真的反对你的方法(我这边+1)
我很高兴你已经确定了“显示顺序”@Shnugo .....我请求 PSK 和 Shnugo 在查询中没有使用 while 循环来显示相同的结果订购。
@Smart003,我已经编辑了答案,你可以看看。【参考方案2】:
试试这个:
drop table if exists #store_data;
create table #store_data ([key] nvarchar(max),[value] nvarchar(max),storeid varchar(100)
)
INSERT INTO #store_data VALUES ('sid','1','1')
INSERT INTO #store_data VALUES ('bid','3','1');
INSERT INTO #store_data VALUES ('time','2019-01-01','1');
INSERT INTO #store_data VALUES ('que','apple','1');
INSERT INTO #store_data VALUES ('sid','2','2');
INSERT INTO #store_data VALUES ('bid','5','2');
INSERT INTO #store_data VALUES ('hrs','6','2');
INSERT INTO #store_data VALUES ('dat','pine','2');
DECLARE @DynamicTSQLStatement NVARCHAR(MAX)
,@ColumnNames NVARCHAR(MAX);
SELECT @ColumnNames = STUFF
(
(
SELECT DISTINCT ',[' + [key] + ']'
FROM #store_data
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET @DynamicTSQLStatement = N'
select ' + @ColumnNames + '
from #store_data
PIVOT
(
MAX([value]) FOR [key] IN (' + @ColumnNames + ')
) PVT
FOR JSON PATH;
';
EXEC sp_executesql @DynamicTSQLStatement;
更改为 SELECT *
以便在 JSON 对象中也获得 storeid
。此外,在 SQL Server 2017 中,您可以使用 STRING_AGG 连接键。
【讨论】:
查询标记为SQL Server 2017
是的,这就是为什么我说他可以使用STRING_AGG
。
为什么要发布 XML 连接技术呢?它隐藏了 actual 解决方案,即在将数据转换为 JSON 之前对数据进行 PIVOT
您可能会在关于不存在的隐式排序顺序的问题下方阅读我的评论..
@Shnugo 是的,你是对的。这就是为什么我指出我们可以使用SELECT *
来获取每个对象中的storeid
。放在那里似乎很正常,因为它是用来对数据进行分组的。以上是关于在sql server中将行/表记录转换为json文档的主要内容,如果未能解决你的问题,请参考以下文章
sql server 中将由逗号“,”分割的一个字符串,转换为一个表,并应用与 in 条件