Domanda

Ho una tabella 'Task' con le seguenti colonne (il TaskOrder è per ordinare i bambini nell'ambito di applicazione del genitore, non l'intera tabella):

TaskId
ParentTaskId
TaskName
TaskOrder

Ho questa query CTE di restituire tutte le righe:

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

Questa query restituisce tutte le attività ordinate dal loro livello come ci si aspetterebbe. Come posso cambiarlo per ordinare i risultati in loro ordine gerarchico, come di seguito?

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

Grazie.

Modifica:. La risposta dovrebbe funzionare con una numbr illimitato di livelli

È stato utile?

Soluzione 2

risolto il problema utilizzando una variante del metodo href="https://stackoverflow.com/questions/539155/ordering-recursive-query-results-in-sql-2005/539211#539211"> , ma non sto mantenendo il percorso del nodo in ogni nodo, in modo da poter più facilmente spostarli intorno all'albero. Invece ho cambiato la mia colonna 'OrderBy' da un int a varchar (3) a sinistra imbottita con zeri modo che io possa concatenare in un master 'OrderBy' per tutte le righe restituite.

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

Questa operazione riporta:

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

E 'non consente una gerarchia senza limiti (max 10 livelli / max 1000 bambini per nodo padre - se avessi iniziato l'OrderBy a 0). Ma più che sufficiente per le mie esigenze

Altri suggerimenti

Un modo che si possa fare è quello di aggiungere una colonna gerarchia che ha tutti gli ID precedenti in un elenco:

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

Si noti che questo presuppone che TaskId è un ID di stringa-based. In caso contrario, si dovrebbe lanciare ad un varchar prima di concatenazione di esso.

Non hai bisogno di tutta quella roba unione, credo che questo dovrebbe funzionare:

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

Dal momento che non è necessario specificare "ORDER BY", come si aspetta che li restituisce in un ordine particolare (diverso sperando che il Query Analyzer funzionerà in qualche modo previsto?).

Se si desidera in ParentTaskId, ordine TaskId, quindi selezionare il TaskId come ParentTaskId e NULL come TaskId nel primo elemento UNION; poi

ORDER BY ParentTaskId, TaskId?

scroll top