从 Table 值输出 JSON 类型数组而不重复的最佳做法是什么?
What is the best practise for outputting JSON Type arrays from Table values without repetition?
我有以下 SQL 数据,我正尝试将其输出为结构化 JSON 字符串,如下所示:
Table数据
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
}
]
}
]
}
]
}
我已经尝试了几种输出它的方法,但我很难停止重复的 Container 和 Material Id 记录。有没有人能够展示从这样的 table 中提取 JSON 的最佳工作实践?
您可以使用以下查询
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
嗯,它并不漂亮,但这似乎有效:
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
AUTO 将为您构造 JSON,但仅遵循查询中使用的数据 table 的结构。由于数据以单个 table 开始“平坦”,因此 AUTO 不会创建任何结构。所以我在这里应用的技巧是使用 WITH CTE 将这个平面数据重组为三个虚拟 tables,它们的关系具有必要的结构。
这里的一切都非常敏感,正常关系 SQL 不会如此。例如,仅更改 JOIN 的顺序将重构 JSON 层次结构,即使这对正常的 SQL 查询没有影响。
我还不得不尝试使用 table 和列别名(lot)来让它在 [=24] 中的所有内容上加上正确的名称=].
我有以下 SQL 数据,我正尝试将其输出为结构化 JSON 字符串,如下所示:
Table数据
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
}
]
}
]
}
]
}
我已经尝试了几种输出它的方法,但我很难停止重复的 Container 和 Material Id 记录。有没有人能够展示从这样的 table 中提取 JSON 的最佳工作实践?
您可以使用以下查询
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
嗯,它并不漂亮,但这似乎有效:
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
AUTO 将为您构造 JSON,但仅遵循查询中使用的数据 table 的结构。由于数据以单个 table 开始“平坦”,因此 AUTO 不会创建任何结构。所以我在这里应用的技巧是使用 WITH CTE 将这个平面数据重组为三个虚拟 tables,它们的关系具有必要的结构。
这里的一切都非常敏感,正常关系 SQL 不会如此。例如,仅更改 JOIN 的顺序将重构 JSON 层次结构,即使这对正常的 SQL 查询没有影响。
我还不得不尝试使用 table 和列别名(lot)来让它在 [=24] 中的所有内容上加上正确的名称=].