【问题标题】:Update hierarchy after deletion of row删除行后更新层次结构
【发布时间】: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 作为输入,并删除它,以及它的子元素(如果有)。然后,它会重新计算 FullPathOrder 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


【解决方案1】:

我设法用 CTE 更新了层次结构。由于我有订单,我可以将它附加到Hierarchy,基于之前已经更新的分支(父)。

;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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多