1

我有下面的 Json 对象。我需要用逗号(,)分隔的任务名称。

{
  "Model": [
    {
      "ModelName": "Test Model",    
      "Object": [
         {
           "ID": 1,
           "Name": "ABC",
           "Task" : [
             {
                TaskID : 1222,
                Name: "TaskA"
             },
             {
                TaskID : 154,
                Name: "TaskB"
             }
           ]
         },
         {
           "ID": 11,
           "Name": "ABCD",
           "Task" : [
             {
                TaskID : 222,
                Name: "TaskX"
             },
             {
               TaskID : 234,
               Name: "TaskY"
             }
           ]
        },         
     ]  
 }]}

预期的输出应在下表中。我需要任务名称应该用逗号分隔。

ModelName   ObjectID   ObjectName  TaskName
Test Model     1          ABC      TaskA, TaskB
Test Model     11         ABCD     TaskX, TaskY

我尝试了以下查询。但我不知道如何对任务名称进行分组。

                  SELECT   S1.ModelName,
                           S2.ID  AS ObjectID, 
                           S2.Name AS ObjectName, 
                           S3.TaskName
                     FROM TableA 
                       CROSS APPLY OPENJSON(JsonData)
                         WITH (Model NVARCHAR(MAX) '$.Model[0]' AS JSON) S1
                       CROSS APPLY OPENJSON (S1.Model) 
                         WITH (Object NVARCHAR(MAX) '$.Object' AS JSON,
                               ID  INT '$.ID',
                               Name NVARCHAR(250) '$.Name') S2
                       CROSS APPLY OPENJSON (S2.Object) 
                         WITH (Task NVARCHAR(MAX) '$.Task' AS JSON ,
                               TaskName NVARCHAR(MAX) '$.TaskName') S3  
4

2 回答 2

0

您需要使用适用于数据库版本 SQL Server 2017 及更高版本的STRING_AGG()函数,以及以下表达式GROUP BY

SELECT S1.ModelName, S2.ID  AS ObjectID, S2.Name AS ObjectName, 
       STRING_AGG(S3.TaskName, ',') WITHIN GROUP (ORDER BY TaskName) AS TaskName
  FROM <rest of your query>
 GROUP BY S1.ModelName, S2.ID, S2.Name

作为一个完整的查询:

SELECT S1.ModelName, S3.ObjectID, S3.ObjectName,
       STRING_AGG(S4.TaskName, ',') WITHIN GROUP (ORDER BY S4.TaskName) AS TaskName
  FROM TableA 
 CROSS APPLY OPENJSON(JsonData)
  WITH (ModelName NVARCHAR(255) '$.Model[0].ModelName') S1
 CROSS APPLY OPENJSON (JsonData) 
  WITH (Object NVARCHAR(MAX)    '$.Model[0].Object' AS JSON) S2
 CROSS APPLY OPENJSON (S2.Object)   
  WITH (ObjectID       INT           '$.ID',
        ObjectName     NVARCHAR(255) '$.Name',
        Task           NVARCHAR(MAX) '$.Task' AS JSON) S3 
 CROSS APPLY OPENJSON (S3.Task) 
  WITH (TaskID   NVARCHAR(MAX) '$.TaskID',
        TaskName NVARCHAR(MAX) '$.Name') S4
 GROUP BY S1.ModelName, S3.ObjectID, S3.ObjectName

使用WITHIN GROUP (ORDER BY TaskName)是可选的,如果您不想订购,那么您可以从函数中删除该部分,如下面的演示所示:

Demo

于 2020-05-04T16:54:34.043 回答
0

您需要使用STRING_AGG()来聚合文本值,一种可能的方法(基于问题中的尝试)是以下语句。任务名称的聚合针对ObjectJSON 数组中的每个项目:

桌子:

CREATE TABLE TableA (JsonData varchar(max))
INSERT INTO TableA (JsonData) VALUES ('{
  "Model": [
    {
      "ModelName": "Test Model",    
      "Object": [
         {
           "ID": 1,
           "Name": "ABC",
           "Task" : [
             {
                "TaskID" : 1222,
                "Name": "TaskA"
             },
             {
                "TaskID" : 154,
                "Name": "TaskB"
             }
           ]
         },
         {
           "ID": 11,
           "Name": "ABCD",
           "Task" : [
             {
                "TaskID" : 222,
                "Name": "TaskX"
             },
             {
               "TaskID" : 234,
               "Name": "TaskY"
             }
           ]
        }         
     ]  
 }]}')

陈述:

SELECT 
   j1.ModelName,
   j2.ObjectID, j2.ObjectName,
   c.TaskName
FROM TableA t
CROSS APPLY OPENJSON(t.JsonData, '$.Model[0]') WITH (
   ModelName varchar(50) '$.ModelName',
   Object nvarchar(max) '$.Object' AS JSON
) j1
CROSS APPLY OPENJSON(j1.Object, '$') WITH (
   ObjectID int '$.ID',
   ObjectName varchar(50) '$.Name',
   Task nvarchar(max) '$.Task' AS JSON
) j2
CROSS APPLY (
   SELECT STRING_AGG([Name], ',') AS TaskName
   FROM OPENJSON (j2.Task, '$') WITH (Name varchar(50) '$.Name')
) c
于 2020-05-04T19:37:03.823 回答