Pregunta

Tengo una tabla 'tarea' con las siguientes columnas (la TaskOrder es para pedir a los niños en el ámbito de los padres, no toda la tabla):

TaskId
ParentTaskId
TaskName
TaskOrder

Tengo esta consulta CTE para devolver todas las filas:

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

Esta consulta devuelve todas las tareas ordenadas por su nivel como era de esperar. ¿Cómo puedo cambiarlo para ordenar los resultados en su orden jerárquico que a continuación?

- Task 1
-- Task 1 Subtask 1
-- Task 1 Subtask 2
- Task 2
- Task 3

Gracias.

Editar:. La respuesta debe trabajar con un numbr ilimitado de niveles

¿Fue útil?

Solución 2

resuelto el problema usando una variación de href="https://stackoverflow.com/questions/539155/ordering-recursive-query-results-in-sql-2005/539211#539211"> método de Mark , pero no voy a retener la ruta de nodo en cada nodo, para que pueda moverse más fácilmente alrededor del árbol. En su lugar he cambiado mi columna 'OrdenarPor' de un int a varchar (3) izquierda-rellenado con ceros para que pueda concatenar en un maestro 'OrdenarPor' para todas las filas devueltas.

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

Esto devuelve:

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

no permite una jerarquía ilimitada (máximo 10 niveles / max 1000 niños por nodo padre - si es que había empezado el OrdenarPor a 0). Pero más que suficiente para mis necesidades

Otros consejos

Una forma de poder hacer esto es añadir una columna de jerarquía que tiene todos los ID anteriores en una 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

Tenga en cuenta que esto supone que TaskId es un identificador basado en cadena. Si no, usted debe echarlo a un varchar antes de la concatenación de él.

No es necesario todo eso unión, creo que esto debería funcionar:

select
 TaskId,
 ParentTaskId,
 [Name],
 COALESCE(ParentTaskId, TaskId) as groupField
from
 task
order by
 COALESCE(ParentTaskId, TaskId), ParentTaskId, TaskId

Ya que no especifican "ORDER BY", ¿cómo espera que los devuelve en ningún orden en particular (que no sea esperando que el analizador de consultas va a funcionar de alguna manera esperada?).

Si lo desea, en ParentTaskId, orden TaskId, a continuación, seleccione el TaskId como ParentTaskId y NULL como TaskId en el primer elemento de unión; entonces

ORDER BY ParentTaskId, TaskId?

scroll top