从 SQL 服务器以字典(字符串索引列表)表示法输出 json
Output json in dictionary (string-indexed list) notation from SQL Server
我在 SQL 服务器中设置了这个结果:
ID CUSTOMER PRODUCT DATE COUNT
A1 Walmart Widget 1/1/2020 5
B2 Amazon Thingy 1/2/2020 10
C3 Target Gadget 2/1/2020 7
我想将它输出为 json,SQL 服务器 2016+ 有足够的能力来做。但我想要一个由 id 索引的传统字符串索引列表 ('dictionary'),如下所示:
目标
{
"A1": {"Customer":"Walmart", "Product":"Widget", "Date":"1/1/2020", "Count":5 },
"B2": {"Customer":"Amazon", "Product":"Thingy", "Date":"1/2/2020", "Count":10},
"C3": {"Customer":"Target", "Product":"Gadget", "Date":"2/1/2020", "Count":7 }
}
但是,典型的 select * from table for json path
输出为未索引的对象数组:
当前状态
[
{"Id":"A1", "Customer":"Walmart", "Product":"Widget", "Date":"1/1/2020", "Count":5 },
{"Id":"B2", "Customer":"Amazon", "Product":"Thingy", "Date":"1/2/2020", "Count":10},
{"Id":"C3", "Customer":"Target", "Product":"Gadget", "Date":"2/1/2020", "Count":7 }
]
其他 for json
修饰符,如 root
表面上看起来很相关,但据我所知,只是在外部根节点中捕获整个对象的美化字符串连接。
如何使用本机(性能)SQL 服务器 json
函数完成上述表示法?
不幸的是,您想要一个 JSON 结果,该结果具有从数据派生的多个值(A1、B2 和 C3)。这意味着您需要将数据聚合到一行中。通常,for json path
会想要创建一个值数组,每行一个值。
所以,这应该可以满足您的要求:
select json_query(max(case when id = 'A1' then j.p end)) as A1,
json_query(max(case when id = 'B2' then j.p end)) as B2,
json_query(max(case when id = 'B3' then j.p end)) as B3
from t cross apply
(select t.customer, t.product, t.date, t.count
for json path
) j(p)
for json path;
Here 是一个 db<>fiddle.
然而,它不容易推广。对于一般解决方案,您可能需要进行字符串操作。
问题被标记为 sql2016,string_agg() 将不起作用...(使用 xpath 或自定义聚合进行聚合)
declare @t table
(
Id varchar(10),
CUSTOMER varchar(50),
PRODUCT varchar(50),
[DATE] date,
[COUNT] int
);
insert into @t(Id, CUSTOMER, PRODUCT, [DATE], [COUNT])
values
('A1','Walmart','Widget','20200101', 5),
('B2','Amazon','Thingy','20200201', 10),
('C3','Target','Gadget','20200102', 7);
select concat('{', STRING_AGG(thejson, ','), '}')
from
(
select concat('"', STRING_ESCAPE(Id, 'json'), '":', (select CUSTOMER, PRODUCT, DATE, COUNT for json path, without_array_wrapper )) as thejson
from @t
) as src;
我认为您无法使用 FOR JSON AUTO
或 FOR JSON PATH
生成具有可变键名的 JSON 输出,但如果您可以升级到 SQL Server 2017 ,以下方法仅使用 JSON 内置支持,是一种可能的选择:
Table:
CREATE TABLE Data (
Id varchar(2),
Customer varchar(50),
Product varchar(50),
[Date] date,
[Count] int
)
INSERT INTO Data
(Id, Customer, Product, [Date], [Count])
VALUES
('A1', 'Walmart', 'Widget', '20200101', 5),
('B2', 'Amazon', 'Thingy', '20200102', 10),
('C3', 'Target', 'Gadget', '20200201', 7)
声明:
DECLARE @json nvarchar(max) = N'{}'
SELECT @json = JSON_MODIFY(
@json,
CONCAT(N'$."', ID, N'"'),
JSON_QUERY((SELECT Customer, Product, [Date], [Count] FOR JSON PATH, WITHOUT_ARRAY_WRAPPER))
)
FROM Data
SELECT @json
结果:
{"A1":{"Customer":"Walmart","Product":"Widget","Date":"2020-01-01","Count":5},"B2":{"Customer":"Amazon","Product":"Thingy","Date":"2020-01-02","Count":10},"C3":{"Customer":"Target","Product":"Gadget","Date":"2020-02-01","Count":7}}
备注:
JSON_MODIFY()
中的 path
参数使用变量或表达式代替值在 SQL Server 2017+ 中可用。 JSON_QUERY()
用于防止特殊字符转义。
我在 SQL 服务器中设置了这个结果:
ID CUSTOMER PRODUCT DATE COUNT
A1 Walmart Widget 1/1/2020 5
B2 Amazon Thingy 1/2/2020 10
C3 Target Gadget 2/1/2020 7
我想将它输出为 json,SQL 服务器 2016+ 有足够的能力来做。但我想要一个由 id 索引的传统字符串索引列表 ('dictionary'),如下所示:
目标
{
"A1": {"Customer":"Walmart", "Product":"Widget", "Date":"1/1/2020", "Count":5 },
"B2": {"Customer":"Amazon", "Product":"Thingy", "Date":"1/2/2020", "Count":10},
"C3": {"Customer":"Target", "Product":"Gadget", "Date":"2/1/2020", "Count":7 }
}
但是,典型的 select * from table for json path
输出为未索引的对象数组:
当前状态
[
{"Id":"A1", "Customer":"Walmart", "Product":"Widget", "Date":"1/1/2020", "Count":5 },
{"Id":"B2", "Customer":"Amazon", "Product":"Thingy", "Date":"1/2/2020", "Count":10},
{"Id":"C3", "Customer":"Target", "Product":"Gadget", "Date":"2/1/2020", "Count":7 }
]
其他 for json
修饰符,如 root
表面上看起来很相关,但据我所知,只是在外部根节点中捕获整个对象的美化字符串连接。
如何使用本机(性能)SQL 服务器 json
函数完成上述表示法?
不幸的是,您想要一个 JSON 结果,该结果具有从数据派生的多个值(A1、B2 和 C3)。这意味着您需要将数据聚合到一行中。通常,for json path
会想要创建一个值数组,每行一个值。
所以,这应该可以满足您的要求:
select json_query(max(case when id = 'A1' then j.p end)) as A1,
json_query(max(case when id = 'B2' then j.p end)) as B2,
json_query(max(case when id = 'B3' then j.p end)) as B3
from t cross apply
(select t.customer, t.product, t.date, t.count
for json path
) j(p)
for json path;
Here 是一个 db<>fiddle.
然而,它不容易推广。对于一般解决方案,您可能需要进行字符串操作。
问题被标记为 sql2016,string_agg() 将不起作用...(使用 xpath 或自定义聚合进行聚合)
declare @t table
(
Id varchar(10),
CUSTOMER varchar(50),
PRODUCT varchar(50),
[DATE] date,
[COUNT] int
);
insert into @t(Id, CUSTOMER, PRODUCT, [DATE], [COUNT])
values
('A1','Walmart','Widget','20200101', 5),
('B2','Amazon','Thingy','20200201', 10),
('C3','Target','Gadget','20200102', 7);
select concat('{', STRING_AGG(thejson, ','), '}')
from
(
select concat('"', STRING_ESCAPE(Id, 'json'), '":', (select CUSTOMER, PRODUCT, DATE, COUNT for json path, without_array_wrapper )) as thejson
from @t
) as src;
我认为您无法使用 FOR JSON AUTO
或 FOR JSON PATH
生成具有可变键名的 JSON 输出,但如果您可以升级到 SQL Server 2017 ,以下方法仅使用 JSON 内置支持,是一种可能的选择:
Table:
CREATE TABLE Data (
Id varchar(2),
Customer varchar(50),
Product varchar(50),
[Date] date,
[Count] int
)
INSERT INTO Data
(Id, Customer, Product, [Date], [Count])
VALUES
('A1', 'Walmart', 'Widget', '20200101', 5),
('B2', 'Amazon', 'Thingy', '20200102', 10),
('C3', 'Target', 'Gadget', '20200201', 7)
声明:
DECLARE @json nvarchar(max) = N'{}'
SELECT @json = JSON_MODIFY(
@json,
CONCAT(N'$."', ID, N'"'),
JSON_QUERY((SELECT Customer, Product, [Date], [Count] FOR JSON PATH, WITHOUT_ARRAY_WRAPPER))
)
FROM Data
SELECT @json
结果:
{"A1":{"Customer":"Walmart","Product":"Widget","Date":"2020-01-01","Count":5},"B2":{"Customer":"Amazon","Product":"Thingy","Date":"2020-01-02","Count":10},"C3":{"Customer":"Target","Product":"Gadget","Date":"2020-02-01","Count":7}}
备注:
JSON_MODIFY()
中的 path
参数使用变量或表达式代替值在 SQL Server 2017+ 中可用。 JSON_QUERY()
用于防止特殊字符转义。