Решил проблему, используя вариант Метод Марка , но я не сохраняю путь к узлу в каждом узле, поэтому мне легче перемещать их по дереву. Вместо этого я изменил свой столбец «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 Task One 001
15 1 001 Task One / Task One 001001
2 NULL 002 Task Two 002
7 2 001 Task Two / Task One 002001
14 7 001 Task Two / Task One / Task One 002001001
8 2 002 Task Two / Task Two 002002
9 8 001 Task Two / Task Two / Task One 002002001
10 8 002 Task Two / Task Two / Task Two 002002002
11 8 003 Task Two / Task Two / Task Three 002002003
3 NULL 003 Task Three 003
4 NULL 004 Task Four 004
13 4 001 Task Four / Task One 004001
5 NULL 005 Task Five 005
6 NULL 006 Task Six 006
17 NULL 007 Task Seven 007
18 NULL 008 Task Eight 008
19 NULL 009 Task Nine 009
21 19 001 Task Nine / Task One 009001
20 NULL 010 Task Ten 010
Он не допускает неограниченной иерархии (максимум 10 уровней / максимум 1000 дочерних элементов на родительский узел - если бы я начал OrderBy с 0), но более чем достаточно для моих нужд.