2

我在 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 server 2016+ 有很多功能。但我想要一个由 id 索引的传统字符串索引列表(“字典”),如下所示:

目标

{
  "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函数完成上述表示法?

4

3 回答 3

1

不幸的是,您需要一个从数据派生的具有多个值(A1、B2 和 C3)的 JSON 结果。这意味着您需要将数据聚合到一行中。通常,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;

是一个 db<>fiddle。

但是,它不容易推广。对于一般解决方案,您可能需要进行字符串操作。

于 2020-02-03T16:35:36.183 回答
1

问题标记为 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;
于 2020-02-03T16:41:41.313 回答
1

我不认为您可以使用FOR JSON AUTOor生成带有变量键名的 JSON 输出FOR JSON PATH,但如果您可以升级到 SQL Server 2017,则可以使用以下仅使用 JSON 内置支持的方法:

桌子:

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}}

笔记:

SQL Server 2017+ 中可以使用变量或表达式代替path参数 in的值。用于防止特殊字符的转义。JSON_MODIFY()JSON_QUERY()

于 2020-02-03T18:14:00.637 回答