我有一个带有以下列的'Task'表(TaskOrder用于排序父级范围内的子级,而不是整个表):
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
感谢。
修改:答案应该使用无限数量的等级。
答案 0 :(得分:3)
您可以这样做的一种方法是添加一个层次结构列,列中包含所有以前的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。
答案 1 :(得分:2)
使用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处启动OrderBy)但足以满足我的需求。
答案 2 :(得分:1)
你不需要所有联盟的东西,我认为这应该有效:
select
TaskId,
ParentTaskId,
[Name],
COALESCE(ParentTaskId, TaskId) as groupField
from
task
order by
COALESCE(ParentTaskId, TaskId), ParentTaskId, TaskId
答案 3 :(得分:0)
由于你没有指定“ORDER BY”,你怎么期望它以任何特定的顺序返回它们(除了希望查询分析器能以某种预期的方式工作?)。
如果你想在ParentTaskId,TaskId顺序中使用它,那么在第一个UNION元素中选择TaskId作为ParentTaskId和NULL作为TaskId;然后
ORDER BY ParentTaskId,TaskId?