【发布时间】:2020-07-17 17:56:36
【问题描述】:
我有一个包含树状数据的表(分层设计)。这是一个小样本:
+----+----------+-----------+-------+----------+---------+
| 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 表示哪个项目拥有分层数据集
ParentID是父节点的ID,在ID上有一个外键。
Order 是一个分支中元素的排名。例如,ID 1, 2 and 7 在同一个节点上,而3 and 4 在另一个节点上。
FullPath 使用 ID 显示顺序(出于系统使用和性能原因)。
Hierarchy 是向用户显示的列,它向 UI 显示层次结构。它会在每次插入、更新和删除后自动计算,这是我遇到的问题。
我为删除表中的元素创建了一个过程。它接收要删除的元素的 ID 作为输入,并删除它,以及它的子元素(如果有)。然后,它会重新计算 FullPath 和 Order Column 。这样就可以了。
问题是当我尝试更新 Hierarchy 列时。我使用这个程序:
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
当我删除订单比其他项目低并且他们有孩子的项目时,这会失败。
例如,如果我删除第 3 项,第 4 项 Hierachy 将被更正(1.1),但它的子项不会(它将保持在 1.2.1,而应该是 1.1.1)。我添加了 order by 以确保父母首先更新,但没有变化。
我的错误是什么,我真的不知道如何解决这个问题。
【问题讨论】:
-
看起来您真的接近于将 HierarchyID 与
Hierarchy列一起使用。如果您承诺,则可以使用GetReparentedValue()方法和IsDescendantOf()来查找特定节点的所有子节点,然后将整个子树移动到新父节点下。 -
我不知道有系统方法可以解决这个问题。如果它可以简化我的工作,我将研究 SqlHierachyId 类型。谢谢!
-
没问题。我要给出的一个提示是使用 PK 值作为层次结构路径的组成部分。也就是说,您的 id 5 的层次结构将是
/1/4/5/。
标签: sql-server stored-procedures hierarchy hierarchical-data