[英]How to generate hierarchical JSON data with Microsoft SQL Server 2016?
我正在使用Microsoft SQL Server 2016 。 此版本支持 JSON。
我有一個包含以下數據的Person表:
人名 | 父親身份 | 姓名 |
---|---|---|
1 | 空 | 4 祖父 |
2 | 1 | 第三位祖父 |
3 | 2 | 2 祖父 |
4 | 3 | 祖父 |
5 | 4 | 父親 |
6 | 4 | 叔叔 |
7 | 6 | 表哥 |
8 | 5 | 兄弟 |
9 | 5 | 我 |
我運行以下查詢:
WITH Persons_CTE AS(
SELECT PersonId, FatherId, Name FROM Persons WHERE FatherId IS NULL
UNION ALL
SELECT P.PersonId, P.FatherId, P.Name FROM Persons P JOIN Persons_CTE PCTE
ON PCTE.PersonId = P.FatherId)
SELECT P.Name as Name, PCTE.Name as Children FROM Persons_CTE PCTE LEFT JOIN Persons P
ON P.PersonId = PCTE.FatherId
FOR JSON PATH
查詢生成以下結果:
[
{
"Children":"4th Grand Father"
},
{
"Name":"4th Grand Father",
"Children":"3rd Grand Father"
},
{
"Name":"3rd Grand Father",
"Children":"2nd Grand Father"
},
{
"Name":"2nd Grand Father",
"Children":"Grand Father"
},
{
"Name":"Grand Father",
"Children":"Father"
},
{
"Name":"Grand Father",
"Children":"Uncle"
},
{
"Name":"Uncle",
"Children":"Cousin"
},
{
"Name":"Father",
"Children":"Brother"
},
{
"Name":"Father",
"Children":"Me"
}
]
我希望查詢結果為以下分層格式。 我該怎么做?
[
{
"Name":"4th Grand Father",
"Children":[
{
"Name":"3rd Grand Father",
"Children":[
{
"Name":"2nd Grand Father",
"Children":[
{
"Name":"Grand Father",
"Children":[
{
"Name":"Father",
"children":[
{
"Name":"Brother"
},
{
"Name":"Me"
}
]
},
{
"Name":"Uncle",
"children":[
{
"Name":"Cousin"
}
]
}
]
}
]
}
]
}
]
}
]
當然 使用遞歸 CTE 實現 Json 樹將非常困難(如果不是不可能的話)。
ALTER FUNCTION fn_Json(@PersonId INT, @IsRoot INT )
RETURNS VARCHAR(MAX)
BEGIN
DECLARE @Json NVARCHAR(MAX) = '{}', @Name NVARCHAR(MAX) , @Children NVARCHAR(MAX)
SET @Json =
(SELECT P.Name ,JSON_QUERY(dbo.fn_Json(P.PersonId, 2) ) AS Children
FROM dbo.Persons AS P
WHERE P.FatherId = @PersonId
FOR JSON AUTO);
IF(@IsRoot = 1)
BEGIN
SELECT @Name = P.Name FROM dbo.Persons AS P WHERE P.PersonId = @PersonId
SET @Json = '{"Name":"' + @Name + '","Children":' + CAST(@Json AS NVARCHAR(MAX)) + '}'
SET @IsRoot = 2
END
RETURN @Json
END
去
值得一提的是,如果其內部對象無效,則無法構建函數。 因此,有必要將函數構建為:
CREATE FUNCTION fn_Json(@PersonId INT, @IsRoot INT)
RETURNS VARCHAR(MAX)
BEGIN
RETURN 1
END
然后使用拳頭代碼。 如果您希望根節點包含在集合中
@IsRoot = 1
如果不是@IsRoot = 2
或其他一些值
不幸的是,遞歸 CTe 不能用於生成分層 json 。 遞歸 CTE 的輸出仍然是平坦的結果。
創建分層輸出的唯一方法是為每個級別創建單獨的 CTE,然后加入 using FOR JSON AUTO
准備表:
declare @t table (PersonId int, FatherId int, Name nvarchar(20));
insert into @t(PersonId, FatherId, Name)
values
(1, NULL, '4th Grand Father'),
(2, 1, '3rd Grand Father'),
(3, 2, '2nd Grand Father'),
(4, 3, 'Grand Father'),
(5, 4, 'Father'),
(6, 4, 'Uncle'),
(7, 6, 'Cousin'),
(8, 5, 'Brother'),
(9, 5, 'Me');
-- 分層查詢:
WITH
Persons_CTE1 AS(
SELECT PersonId, FatherId, Name FROM @t WHERE FatherId IS NULL
),
Persons_CTE2 AS(
SELECT P.PersonId, P.FatherId, P.Name
from @t P
WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE1)
),
Persons_CTE3 AS(
SELECT P.PersonId, P.FatherId, P.Name
from @t P
WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE2)
),
Persons_CTE4 AS(
SELECT P.PersonId, P.FatherId, P.Name
from @t P
WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE3)
),
Persons_CTE5 AS(
SELECT P.PersonId, P.FatherId, P.Name
from @t P
WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE4)
),
Persons_CTE6 AS(
SELECT P.PersonId, P.FatherId, P.Name
from @t P
WHERE P.FatherId IN (SELECT PersonId FROM Persons_CTE5)
)
select Persons_CTE1.Name, Persons_CTE2.Name, Persons_CTE3.Name,
Persons_CTE4.Name, Persons_CTE5.Name, Persons_CTE6.Name
from Persons_CTE1
LEFT JOIN Persons_CTE2
ON Persons_CTE2.FatherId = Persons_CTE1.PersonId
LEFT JOIN Persons_CTE3
ON Persons_CTE3.FatherId = Persons_CTE2.PersonId
LEFT JOIN Persons_CTE4
ON Persons_CTE4.FatherId = Persons_CTE3.PersonId
LEFT JOIN Persons_CTE5
ON Persons_CTE5.FatherId = Persons_CTE4.PersonId
LEFT JOIN Persons_CTE6
ON Persons_CTE6.FatherId = Persons_CTE5.PersonId
FOR JSON AUTO
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.