Question

J'ai une table « tâche » avec les colonnes suivantes (le TaskOrder est pour commander les enfants dans le cadre de la société mère, et non pas l'ensemble du tableau):

TaskId
ParentTaskId
TaskName
TaskOrder

J'ai cette requête CTE pour retourner toutes les lignes:

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

Cette requête renvoie toutes les tâches ordonnées par leur niveau que vous attendez. Comment puis-je changer pour commander les résultats dans leur ordre hiérarchique comme ci-dessous?

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

Merci.

Edit:. La réponse devrait fonctionner avec un numbr illimité de niveaux

Était-ce utile?

La solution 2

a résolu le problème en utilisant une variante de la méthode Mark , mais je ne suis pas en conservant le chemin de nœud dans chaque nœud, donc je ne peux plus les déplacer facilement autour de l'arbre. Au lieu de cela j'ai changé « OrderBy » colonne d'un int varchar (3) gauche complété par des zéros pour que je puisse les concaténer en un maître « OrderBy » pour toutes les lignes retournées.

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

retourne:

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

Il ne permet pas une hiérarchie illimitée (niveaux maximum 10 / max 1000 enfants par nœud parent - si j'avais commencé le OrderBy à 0). Mais plus que suffisant pour mes besoins

Autres conseils

Une façon vous pouvez faire est d'ajouter une colonne de hiérarchie qui a tous les ID précédents dans une liste:

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

Notez que cela suppose que TaskId est une pièce d'identité basée sur la chaîne. Sinon, vous devriez jeter un varchar avant concaténer.

Vous n'avez pas besoin de tout ce genre de choses de l'union, je pense que cela devrait fonctionner:

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

Puisque vous ne spécifiez pas « ORDER BY », comment voulez-vous qu'il les renvoie dans un ordre particulier (autre que l'espoir de l'analyseur de requête fonctionnera d'une certaine façon attendue?).

Si vous voulez en ParentTaskId, afin TaskId, puis sélectionnez le TaskId comme ParentTaskId et NULL comme TaskId dans le premier élément UNION; puis

ORDER BY ParentTaskId, TaskId?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top