5

我有一個「任務」表具有以下的列(在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 

謝謝。

編輯:答案應該可以使用無限數量的關卡。你可以這樣做

+0

你只是試驗CTE,還是比直接SQL更簡單? – dkretz 2009-02-11 22:53:38

+0

是的,試驗CTE,但如果有更好的解決方案,直接使用SQL我會使用.. – Nick 2009-02-11 23:04:31

回答

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開始排序依據),但更多的對我的需求來說足夠了。

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。

+0

謝謝,希望找到一個解決方案,不需要額外的列;這使得當孩子的任務在父母之間移動時難以維持。 – Nick 2009-02-12 18:23:55

0

由於您沒有指定「ORDER BY」,您如何期望它以任何特定順序返回它們(除了希望查詢分析器能以某種預期的方式工作?)。

如果你想在ParentTaskId,TaskId的順序,然後在第一個UNION元素中選擇TaskId作爲ParentTaskId和NULL作爲TaskId;那麼

ORDER BY ParentTaskId,TaskId?

+0

正確,重大遺漏!我還訂購了一個'order by'列,用於訂購家長中的子女 – Nick 2009-02-12 18:26:19

1

你並不需要所有的工會的東西,我覺得這應該工作:

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