使用SQL Server进行JSON PATH的动态根

时间:2019-05-30 20:39:19

标签: json sql-server

我有一个要呈现给Json对象的关键字表:

ID  Keyword     Text    Value
4   Category    A       10
5   Category    B       20
1   Season      Winter  1
2   Season      Spring  2
3   Season      Summer  3
9   Season      Fall    4
6   UnitType    Ft      Feet
7   UnitType    Set     Set
8   UnitType    $   Dollar

将每个类别归为自己的对象。

我能够创建这个:

{"Keywords":[
{"Keyword":"Category","Values":[{"Value":"10","Text":"A"},{"Value":"20","Text":"B"}]},
{"Keyword":"Season","Values":[{"Value":"1","Text":"Winter"},{"Value":"2","Text":"Spring"},{"Value":"3","Text":"Summer"},{"Value":"4","Text":"Fall"}]},
{"Keyword":"UnitType","Values":[{"Value":"Dollar","Text":"$"},{"Value":"Feet","Text":"Ft"},{"Value":"Set","Text":"Set"}]}
]}

使用:

SELECT T.Keyword AS 'Keyword', 
(SELECT [subT].[Value] AS 'Value', [subT].[Text] AS 'Text' 
FROM tblKeywords subT WHERE subT.Keyword=T.Keyword 
ORDER BY [subT].[Value]
FOR JSON PATH) AS 'Values'
FROM tblKeywords T
GROUP BY T.Keyword
FOR JSON PATH, ROOT('Keywords')

但是我希望能够将子查询的ROOT设置为关键字本身。这有可能吗?

所需的结果是:

{"Keywords":[
{"Category":[{"Value":"10","Text":"A"},{"Value":"20","Text":"B"}]},
{"Season":[{"Value":"1","Text":"Winter"},{"Value":"2","Text":"Spring"},{"Value":"3","Text":"Summer"},{"Value":"4","Text":"Fall"}]},
{"UnitType":[{"Value":"Dollar","Text":"$"},{"Value":"Feet","Text":"Ft"},{"Value":"Set","Text":"Set"}]}
]}

2 个答案:

答案 0 :(得分:2)

结合FOR JSON和字符串操作,但不使用动态语句的另一种可能的方法:

输入:

CREATE TABLE #tblKeywords (
   Id int, 
   [Keyword] nvarchar(50), 
   [Text] nvarchar(50), 
   [Value] nvarchar(50)
);
INSERT INTO #tblKeywords
   (ID, [Keyword], [Text], [Value])
VALUES
   (4, 'Category', 'A',      '10'),
   (5, 'Category', 'B',      '20'),
   (1, 'Season',   'Winter', '1'),
   (2, 'Season',   'Spring', '2'),
   (3, 'Season',   'Summer', '3'),
   (9, 'Season',   'Fall',   '4'),
   (6, 'UnitType', 'Ft',     'Feet'),
   (7, 'UnitType', 'Set',    'Set'),
   (8, 'UnitType', '$',      'Dollar')

T-SQL:

SELECT CONCAT(
   N'{"Keywords":[',
   STUFF(
      (
      SELECT DISTINCT CONCAT(N',{"', k.[Keyword], '":', c.[Json], N'}')
      FROM #tblKeywords k
      CROSS APPLY (
         SELECT [Value], [Text]
         FROM #tblKeywords
         WHERE [Keyword] = k.[Keyword]
         FOR JSON PATH
      ) c([Json])
      FOR XML PATH('')
      ), 1, 1, N''
   ),  
   N']}'
) AS JsonOutput

输出:

JsonOutput

{"Keywords":[{"Category":[{"Value":"10","Text":"A"},{"Value":"20","Text":"B"}]},{"Season":[{"Value":"1","Text":"Winter"},{"Value":"2","Text":"Spring"},{"Value":"3","Text":"Summer"},{"Value":"4","Text":"Fall"}]},{"UnitType":[{"Value":"Feet","Text":"Ft"},{"Value":"Set","Text":"Set"},{"Value":"Dollar","Text":"$"}]}]}

答案 1 :(得分:1)

初始数据:

DROP TABLE IF EXISTS #tblKeywords;
CREATE TABLE #tblKeywords (ID INT, Keyword NVARCHAR(255), [Text] NVARCHAR(255), Value NVARCHAR(255));
INSERT INTO #tblKeywords(ID,Keyword,Text,[Value])VALUES
     (4,'Category','A','10')
    ,(5,'Category','B','20')
    ,(1,'Season','Winter','1')
    ,(2,'Season','Spring','2')
    ,(3,'Season','Summer','3')
    ,(9,'Season','Fall','4')
    ,(6,'UnitType','Ft','Feet')
    ,(7,'UnitType','Set','Set')
    ,(8,'UnitType','$','Dollar')
;

不过,我知道动态SQL:

DECLARE @DynSql NVARCHAR(MAX) = (
    SELECT 'SELECT ' + STUFF((
            SELECT DISTINCT N',(SELECT [subT].[Value] AS [Value], [subT].[Text] AS [Text] 
            FROM #tblKeywords subT 
            WHERE subT.Keyword = ''' + t.Keyword + N''' 
            ORDER BY [subT].[Value]
            FOR JSON PATH
            ) AS [' + t.Keyword + N']' + CHAR(13) + '   '
            FROM #tblKeywords t
            FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)'),1,1,'')
        + 'FOR JSON PATH, ROOT(''Keywords'')'
)
;
--PRINT @DynSql;
EXEC (@DynSql);