订购层次2005
我有一个“任务”表具有以下的列(在TaskOrder是父,而不是整个表的范围内订购儿童):订购层次2005
TaskId ParentTaskId TaskName TaskOrder
我有了这个CTE查询返回的所有行:
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
此查询返回由他们的水平排列如你所期望的所有任务。我如何改变它以按照下面的顺序将结果排序为它们的层次结构顺序?
- Task 1 -- Task 1 Subtask 1 -- Task 1 Subtask 2 - Task 2 - Task 3
谢谢。
编辑:答案应该可以使用无限数量的关卡。你可以这样做
解决使用Mark's method变化的问题,但我不保留在每一个节点的节点的路径,因此我可以更轻松地将它们移动到树上。相反,我将我的'OrderBy'列从int更改为左侧填充了零的varchar(3),所以我可以将它们连接到所有返回行的主'OrderBy'。
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
这将返回:
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
它不会允许无限层次(最大10级每父节点/最大1000名儿童 - 如果我在0开始排序依据),但更多的对我的需求来说足够了。
一种方法是添加具有列表中的所有以前的ID的层次结构柱:
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
注意,这个假设的TaskID是基于字符串的ID。如果没有,你应该在连接它之前把它转换成一个varchar。
谢谢,希望找到一个解决方案,不需要额外的列;这使得当孩子的任务在父母之间移动时难以维持。 – Nick 2009-02-12 18:23:55
由于您没有指定“ORDER BY”,您如何期望它以任何特定顺序返回它们(除了希望查询分析器能以某种预期的方式工作?)。
如果你想在ParentTaskId,TaskId的顺序,然后在第一个UNION元素中选择TaskId作为ParentTaskId和NULL作为TaskId;那么
ORDER BY ParentTaskId,TaskId?
正确,重大遗漏!我还订购了一个'order by'列,用于订购家长中的子女 – Nick 2009-02-12 18:26:19
你并不需要所有的工会的东西,我觉得这应该工作:
select
TaskId,
ParentTaskId,
[Name],
COALESCE(ParentTaskId, TaskId) as groupField
from
task
order by
COALESCE(ParentTaskId, TaskId), ParentTaskId, TaskId
你只是试验CTE,还是比直接SQL更简单? – dkretz 2009-02-11 22:53:38
是的,试验CTE,但如果有更好的解决方案,直接使用SQL我会使用.. – Nick 2009-02-11 23:04:31