使用
Mark's method 的变体解决了问题,但我没有在每个节点中保留节点路径,这样我可以更轻松地将它们移动到树中。相反,我将我的 '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 Name 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开始排序),但对我的需求已经足够了。