Вот ответ:
drop table if exists #t
go
select
*
into
#t
from
(
values
('a10', null, '10'),
('a20', null, '11'),
('a30', 'a20', '18'),
('a50', 'a30', '5'),
('a40', 'a20', '15'),
('a60', null, '12')
) as T(TaskId, ParentTaskId, Label)
;
with cte as
(
select
l = 0,
p = cast('/' + Label as nvarchar(max)),
*
from
#t where ParentTaskId is null
union all
select
l = p.l + 1,
p = p.p + '/' + c.Label,
c.*
from
#t c
inner join
cte p on c.ParentTaskId = p.TaskId
)
select
*
from
cte
order by p, Label
Вам необходимо создать путь от корня вашей задачи к текущей задаче, а затем использовать его для сортировки окончательного результата.Для небольшого набора данных вышеуказанный запрос будет работать нормально.На больших (сотни тысяч) я рекомендую взглянуть на hierarchyid
тип данных:
https://docs.microsoft.com/en-us/sql/t-sql/data-types/hierarchyid-data-type-method-reference?view=sql-server-2017