如何在删除 n 个子项后递归更新/重新索引嵌套的自引用 table?

How to recursively update / re-index a nested self-referencing table after n children are deleted?

我有一个名为 ListItem 的嵌套自引用 table,其中包含我填充了一些示例数据的以下列:

----------------------------------------
| Id   |   ParentId   |   DisplayIndex |
----------------------------------------
| 1000 |   NULL       |   1            |
| 1001 |   1000       |   1            |
| 1002 |   1001       |   1            |
| 1003 |   1001       |   2            |
| 1004 |   1001       |   3            |
| 1005 |   1001       |   4            |
| 1007 |   1001       |   5            |
| 1008 |   1000       |   2            |
| 1009 |   1008       |   1            |
| 1010 |   1008       |   2            |
| 1011 |   1008       |   3            |
| 1012 |   1008       |   4            |
| 1013 |   1008       |   5            |
----------------------------------------

可以在给定时间删除任何一个或多个节点。

如果我删除节点 WHERE Id IN (1003, 1004, 1005, 1011, 1012),我的 table 将如下所示:

----------------------------------------
| Id   |   ParentId   |   DisplayIndex |
----------------------------------------
| 1000 |   NULL       |   1            |
| 1001 |   1000       |   1            |
| 1002 |   1001       |   1            |
| 1007 |   1001       |   5            |
| 1008 |   1000       |   2            |
| 1009 |   1008       |   1            |
| 1010 |   1008       |   2            |
| 1013 |   1008       |   5            |
----------------------------------------

这在我的 DisplayIndex 中留下了空白。我现在有 1, 51, 2, 5。如何有效地将 DisplayIndex 列重新索引为 1, 21, 2, 3 如下所示?

----------------------------------------
| Id   |   ParentId   |   DisplayIndex |
----------------------------------------
| 1000 |   NULL       |   1            |
| 1001 |   1000       |   1            |
| 1002 |   1001       |   1            |
| 1007 |   1001       |   2            |
| 1008 |   1000       |   2            |
| 1009 |   1008       |   1            |
| 1010 |   1008       |   2            |
| 1013 |   1008       |   3            |
----------------------------------------

我对 CTE 还很陌生,知道这是我可能需要走的路,但我不确定如何为每个嵌套级别获取一个从 1 开始的数字,然后为该级别中的每一行自动递增.

好的,看来递归CTE是不必要的。 Window 功能足够了。每个 DisplayIndex 都应该按照 Id 描述的顺序在每个唯一 ParentId:

中分配其值
update ListItem
set
  DisplayIndex = NewIndex
from ListItem
  inner join
  ( 
    select
      Id,
      row_number() over (partition by ParentId order by Id) as NewIndex
    from
      ListItem
  ) as S on ListItem.Id = S.Id

这是示例 fiddle:http://sqlfiddle.com/#!3/e9dfe/2