Ordenando hierarquia dos resultados da consulta recursiva no SQL 2005
-
22-08-2019 - |
Pergunta
Eu tenho uma tabela 'Tarefa' com as seguintes colunas (a TaskOrder é para encomendar as crianças dentro do escopo do pai, não a tabela inteira):
TaskId ParentTaskId TaskName TaskOrder
Eu tenho esta consulta CTE para retornar todas as linhas:
with tasks (TaskId, ParentTaskId, [Name]) as
(
select parentTasks.TaskId,
parentTasks.ParentTaskId,
parentTasks.[Name]
from Task parentTasks
where ParentTaskId is null
union all
select childTasks.TaskId,
childTasks.ParentTaskId,
childTasks.[Name]
from Task childTasks
join tasks
on childTasks.ParentTaskId = tasks.TaskId
)
select * from tasks
Essa consulta retorna todas as tarefas ordenadas pelo seu nível como seria de esperar. Como posso alterá-lo para ordenar os resultados em sua ordem de hierarquia como abaixo?
- Task 1 -- Task 1 Subtask 1 -- Task 1 Subtask 2 - Task 2 - Task 3
Graças.
Editar:. A resposta deve trabalhar com um numbr ilimitado de níveis
Solução 2
resolveu o problema usando uma variação do método de Mark , mas eu não estou mantendo o caminho do nó em cada nó, para que eu possa mais facilmente movê-los ao redor da árvore. Em vez disso eu mudei minha coluna 'OrderBy' a partir de um int para varchar (3) deixou-preenchidos com zeros para que eu possa concatenar-los em um mestre 'OrderBy' para todas as linhas retornadas.
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
Este retornos:
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
Ele não permite uma hierarquia ilimitada (max 10 níveis / max 1000 crianças por nó pai - se eu tinha começado a OrderBy em 0)., Mas mais do que suficiente para minhas necessidades
Outras dicas
Uma maneira que você poderia fazer isso é adicionar uma coluna de hierarquia que tem todas as identificações anteriores em uma lista:
with tasks (TaskId, ParentTaskId, [Name], TaskIdList) as
(
select parentTasks.TaskId,
parentTasks.ParentTaskId,
parentTasks.[Name],
parentTasks.TaskId
from Task parentTasks
where ParentTaskId is null
union all
select childTasks.TaskId,
childTasks.ParentTaskId,
childTasks.[Name],
tasks.TaskIdList + '.' + childTasks.TaskId
from Task childTasks
join tasks
on childTasks.ParentTaskId = tasks.TaskId
)
select TaskId, ParentTaskId, [Name] from tasks
order by TaskIdList
Note que isto assume que TaskId é uma identificação baseada em string. Se não, você deve lançá-lo a um varchar antes concatenando-lo.
Você não precisa de todo esse material da união, eu acho que isso deve funcionar:
select
TaskId,
ParentTaskId,
[Name],
COALESCE(ParentTaskId, TaskId) as groupField
from
task
order by
COALESCE(ParentTaskId, TaskId), ParentTaskId, TaskId
Uma vez que você não especificar "ORDER BY", como você espera que ele retorna-los em qualquer ordem particular (que não espera que o analisador de consulta vai funcionar de alguma forma esperado?).
Se você quiser em ParentTaskId, ordem TaskId, em seguida, selecione o TaskId como ParentTaskId e NULL como TaskId no primeiro elemento da União; então
ORDER BY ParentTaskId, TaskId?