使用Mark 方法的变体解决了这个问题,但我没有在每个节点中保留节点路径,因此我可以更轻松地在树周围移动它们。相反,我将我的 'OrderBy' 列从 int 更改为 varchar(3) 左填充零,这样我就可以将它们连接到所有返回的行的主 'OrderBy' 中。
with tasks (TaskId, ParentTaskId, OrderBy, [Name], RowOrder) as
(
select parentTasks.TaskId,
parentTasks.ParentTaskId,
parentTasks.OrderBy,
parentTasks.[Name],
cast(parentTasks.OrderBy as varchar(30)) 'RowOrder'
from Task parentTasks
where ParentTaskId is null
union all
select childTasks.TaskId,
childTasks.ParentTaskId,
childTasks.OrderBy,
childTasks.[Name],
cast(tasks.RowOrder + childTasks.OrderBy as varchar(30)) 'RowOrder'
from Task childTasks
join tasks
on childTasks.ParentTaskId = tasks.TaskId
)
select * from tasks order by RowOrder
这将返回:
TaskId ParentTaskId OrderBy 名称 RowOrder
-------------------------------------------------- -------------------------
1 NULL 001 任务一 001
15 1 001 任务一/任务一 001001
2 NULL 002 任务二 002
7 2 001 任务二/任务一 002001
14 7 001 任务二/任务一/任务一 002001001
8 2 002 任务二 / 任务二 002002
9 8 001 任务二 / 任务二 / 任务一 002002001
10 8 002 任务二 / 任务二 / 任务二 002002002
11 8 003 任务二 / 任务二 / 任务三 002002003
3 NULL 003 任务三 003
4 NULL 004 任务四 004
13 4 001 任务四/任务一 004001
5 NULL 005 任务五 005
6 NULL 006 任务六 006
17 NULL 007 任务七 007
18 NULL 008 任务八 008
19 NULL 009 任务九 009
21 19 001 任务九 / 任务一 009001
20 NULL 010 任务十 010
它不允许无限的层次结构(每个父节点最多 10 个级别/最多 1000 个子节点 - 如果我从 0 开始 OrderBy),但足以满足我的需要。