问题
I have a table that contains tree-like data (hierarchic design). Here is a small sample:
+----+----------+-----------+-------+----------+---------+
| ID | ParentID | Hierarchy | Order | FullPath | Project |
+----+----------+-----------+-------+----------+---------+
| 1 | null | 1 | 1 | 1 | 1 |
| 2 | null | 2 | 2 | 2 | 1 |
| 3 | 1 | 1.1 | 1 | 1-3 | 1 |
| 4 | 1 | 1.2 | 2 | 1-4 | 1 |
| 5 | 4 | 1.2.1 | 1 | 1-4-5 | 1 |
| 6 | 2 | 2.1 | 1 | 2-6 | 1 |
| 7 | null | 3 | 1 | 1 | 2 |
+----+----------+-----------+-------+----------+---------+
Project
indicates which project owns the hierarchic dataset
ParentID
is the ID of the parent node, it has a foreign key on ID
.
Order
is the rank of the element in one branch. For example, IDs 1, 2 and 7
are on the same node while 3 and 4
are in another.
FullPath
shows the order using the ID (it's for system use and performance reasons).
Hierarchy
is the column displayed to the user, which displays the hierarchy to the UI. It auto calculates after every insert, update and delete, and it's the one I'm having issues.
I created a procedure for deletion elements in the table. It receives as input the ID of the element to delete and deletes it, along with it's children if any. Then, it recalculates the FullPath
and the Order Column
.That works.
Problems is when I try to update the Hierarchy
column. I use this procedure:
SELECT T.ID,
T.ParentID,
CASE WHEN T.ParentID IS NOT NULL THEN
CONCAT(T1.Hierarchy, '.', CAST(T.Order AS NVARCHAR(255)))
ELSE
CAST(T.Order AS NVARCHAR(255))
END AS Hierarchy
INTO #tmp
FROM t_HierarchyTable T
LEFT JOIN t_HierarchyTable T1
ON T1.ID = T.ParentID
WHERE Project = @Project --Variable to only update the current project for performance
ORDER BY T.FullPath
--Update the table with ID as key on tmp table
This fails when I delete items that have lower order than others and they have children.
For example, if I delete the item 3, item 4 Hierachy
will be corrected (1.1), BUT its child won't (it will stay at 1.2.1, while it should be 1.1.1). I added the order by to make sure parents where updated first, but no change.
What is my error, I really don't know how to fix this.
回答1:
I managed to update the hierarchy with a CTE. Since I have the order, I can append it to Hierarchy
, based on the previous branch (parent) who is already updated.
;WITH CODES(ID, sCode, iLevel) AS
(
SELECT
T.[ID] AS [ID],
CONVERT(VARCHAR(8000), T.[Order]) AS [Hierarchy],
1 AS [iLevel]
FROM
[dbo].[data] AS T
WHERE
T.[ParentID] IS NULL
UNION ALL
SELECT
T.[ID] AS [ID],
P.[Hierarchy] + IIF(RIGHT(P.[Hierarchy], 1) <> '-', '-', '') + CONVERT(VARCHAR(8000), T.[Order]) AS [Hierarchy],
P.[iLevel] + 1 AS [iLevel]
FROM
[dbo].[data] AS T
INNER JOIN CODES AS P ON
P.[ID] = T.[ParentID]
WHERE
P.[iLevel] < 100
)
SELECT
[ID], [Hierarchy], [iLevel]
INTO
#CODES
FROM
CODES
来源:https://stackoverflow.com/questions/62959413/update-hierarchy-after-deletion-of-row