This is a part of this question . I have Departments
table which uses HierarchyId
to store hierarchical data.
Id | HieararchyId | Name |
---|---|---|
1 | / | MHz |
2 | /2/ | Finance |
3 | /3/ | IT |
4 | /3/4/ | Software Development |
5 | /3/5/ | QA |
6 | /2/6/ | Accountant |
I want to get this table as JSON
for my TreeView on front side.
What I did:
CREATE FUNCTION dbo.GetDepartmentAsJson
(@departmentId hierarchyid,
@IsRoot int)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE @Json NVARCHAR(MAX) = '{}',
@Id int,
@Name varchar(50),
@Children NVARCHAR(MAX) = '{}',
@Hierar Hierarchyid
SET @Json = (SELECT
t.Id, t.HierarchyId, t.Name,
children = JSON_QUERY(dbo.GetDepartmentAsJson(t.HierarchyId, 2))
FROM Departments t
WHERE t.HierarchyId <> @departmentId
AND t.HierarchyId.IsDescendantOf(@departmentId) = 1
FOR JSON PATH);
IF (@IsRoot = 1)
BEGIN
SELECT
@Id = t.Id,
@Hierar = t.HierarchyId,
@Name = t.Name
FROM
Departments t
WHERE
t.HierarchyId = @departmentId;
SET @Json =
'{"Id":"' CONVERT(varchar(7), @Id)
'","HierarchyId":"' @Hierar.ToString()
'","Name":"' @Name
'","Children":' CAST(@Json AS NVARCHAR(MAX)) '}';
SET @IsRoot = 2;
END
RETURN @Json;
END;
Result:
{
"Id": "1",
"HierarchyId": "/",
"Name": "MHz",
"Children": [
{
"Id": 2,
"HierarchyId": "/2/",
"Name": "Finance",
"Children": [
{
"Id": 6,
"HierarchyId": "/2/6/",
"Name": "Accountant"
}
]
},
/* This should not be listed because already included as a child in Finance */
{
"Id": 6,
"HierarchyId": "/2/6/",
"Name": "Accountant"
},
{
"Id": 3,
"HierarchyId": "/3/",
"Name": "IT",
"Children": [
{
"Id": 4,
"HierarchyId": "/3/4/",
"Name": "Software Development"
},
{
"Id": 5,
"HierarchyId": "/3/5/",
"Name": "QA"
}
]
},
/* They both should not be listed because already included as a child in IT */
{
"Id": 4,
"HierarchyId": "/3/4/",
"Name": "Software Development"
},
{
"Id": 5,
"HierarchyId": "/3/5/",
"Name": "QA"
}
]
}
How can I exclude this child elements which have been already listed in parent element?
CodePudding user response:
You should check the level of the descendant as well
CREATE FUNCTION dbo.GetDepartmentAsJson(@departmentId hierarchyid, @level int)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE @Json NVARCHAR(MAX) = '{}',
@Id int,
@Name varchar(50),
@Childeren NVARCHAR(MAX) = '{}',
@Hierar Hierarchyid
SET @Json = (SELECT
t.Id,
t.HierarchyId,
t.Name,
children = JSON_QUERY(dbo.GetDepartmentAsJson(t.HierarchyId, @level 1))
FROM Departments t
WHERE t.HierarchyId <> @departmentId
AND t.HierarchyId.IsDescendantOf(@departmentId) = 1 and t.HierarchyId.GetLevel() = @level 1
FOR JSON PATH);
IF(@level = 0)
BEGIN
SELECT
@Id = t.Id,
@Hierar = t.HierarchyId,
@Name = t.Name
FROM Departments t
WHERE t.HierarchyId = @departmentId;
SET @Json =
'{"Id":"' CONVERT(varchar(7), @Id)
'","HierarchyId":"' @Hierar.ToString()
'","Name":"' @Name
'","Children":' CAST(@Json AS NVARCHAR(MAX)) '}';
END
return @Json;
END;
The root of the hierarchy is level 0, so select dbo.GetDepartmentAsJson ('/', 0)