1

我有以下 SQL 数据,我试图将其作为结构化 JSON 字符串输出,如下所示:

表数据

TableId ContainerId MaterialId  SizeId
848     1           1           1
849     1           1           2
850     1           2           1
851     1           2           2
852     1           3           1
853     1           4           1
854     2           2           1
855     2           2           2
856     2           2           3

JSON 输出

{
  "container": [
    {
      "id": 1,
      "material": [
        {
          "id": 1,
          "size": [
            {
              "id": 1
            },
            {
              "id": 2
            }
          ]
        },
        {
          "id": 2,
          "size": [
            {
              "id": 1
            },
            {
              "id": 2
            }
          ]
        },
        {
          "id": 3,
          "size": [
            {
              "id": 1
            }
          ]
        },
        {
          "id": 4,
          "size": [
            {
              "id": 1
            }
          ]
        }
      ]
    },
    {
      "id": 2,
      "material": [
        {
          "id": 2,
          "size": [
            {
              "id": 1
            },
            {
              "id": 2
            },
            {
              "id": 3
            }
          ]
        }
      ]
    }
  ]
}

我尝试了几种输出它的方法,但我正在努力阻止重复的容器和材料 ID 记录。有没有人能够演示从这样的表中提取 JSON 的最佳工作实践?

4

2 回答 2

3

好吧,它并不漂亮,但这似乎可行:

WITH
   container As (SELECT distinct containerid As id FROM jsonArray1 As container)
 , material As (SELECT distinct materialid As id, containerid As cid FROM jsonArray1 As material) 
 , size As (SELECT sizeid As id, materialid As tid, containerid As cid FROM jsonArray1 As size) 
SELECT container.id id, material.id id, size.id id
FROM container
JOIN material ON material.cid = container.id 
JOIN size     ON size.tid = material.id AND size.cid = material.cid
FOR JSON AUTO, ROOT

sqlfiddle 示例

AUTO 将为您构建 JSON,但仅遵循查询中使用的数据表的结构。由于数据在单个表中开始是“平面”的,因此 AUTO 不会创建任何结构。所以我在这里应用的技巧是使用 WITH CTE 将这些平面数据重组为三个虚拟表,它们的关系具有必要的结构。

这里的一切都是超级敏感的,而普通的关系 SQL 则不会。例如,仅更改 JOIN 的顺序将重构 JSON 层次结构,即使这对正常的 SQL 查询没有影响。

我还必须使用表和列别名(很多)来让它在 JSON 中的所有内容上放置正确的名称。

于 2021-12-01T16:37:18.927 回答
1

您可以使用以下查询

SELECT CONCAT('{"container": [',string_agg(json,','),']}') as json
FROM 


  (SELECT CONCAT('{"id:"',CAST(ContainerId as nvarchar(100)),
       ',"material":[{',string_agg(json,','),'}]}') as json,
       dense_rank() over(partition by ContainerId order by ContainerId) rnk
  FROM
     (SELECT ContainerId ,MaterialId,CONCAT('"id":',CAST(MaterialId as nvarchar(100))
           ,',"size":[',string_agg('{"id":' + CAST(SizeId as nvarchar(100)) + '}',','),']') as json
         
     FROM tb  
     GROUP BY ContainerId,MaterialId) T
  GROUP BY ContainerId) T

GROUP BY rnk

db<>fiddle中的演示

于 2021-12-01T16:32:59.980 回答