Commande de la hiérarchie des résultats de requête récursive dans SQL 2005
-
22-08-2019 - |
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
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?