如何在删除 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, 5
和 1, 2, 5
。如何有效地将 DisplayIndex
列重新索引为 1, 2
和 1, 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
我有一个名为 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, 5
和 1, 2, 5
。如何有效地将 DisplayIndex
列重新索引为 1, 2
和 1, 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