5

У меня есть таблица А «задачу» со следующими столбцами (TaskOrder для заказа детей в рамках родительского, а не вся таблица):Упорядочение из рекурсивных результатов запроса в SQL 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

+0

Да, экспериментируя с CTE, но если есть лучшее решение с прямым SQL, я буду использовать это. – Nick

ответ

2

решена проблема с использованием изменений Mark's method, но я не сохраняя путь узла в каждом узле, так Я могу легче перемещать их вокруг дерева. Вместо этого я изменил свой столбец «OrderBy» от int до varchar (3), оставленный с нулями слева, поэтому я могу объединить их в master 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 детей в родительский узел - если бы я начал OrderBy в 0), но более чем достаточно для моих нужд.

3

Одним из способов вы можете сделать это, чтобы добавить иерархии столбца, который имеет все предыдущие идентификаторы в списке:

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

0

Поскольку вы не указываете «ORDER BY», как вы ожидаете, что он вернет их в каком-либо конкретном порядке (кроме надежд на то, что анализатор запросов будет работать каким-то ожидаемым образом?).

Если вы хотите его в ParentTaskId, TaskId порядке, выберите TaskId как ParentTaskId и NULL как TaskId в первом элементе UNION; затем

ORDER BY ParentTaskId, TaskId?

+0

Правильно, большой упущение! У меня есть столбец «заказать», чтобы упорядочить детей внутри родителя. – Nick

1

Вам не нужны все, что союзные вещи, я думаю, что это должно работать:

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

Почти, но работает только для двух уровней. Мне нужно больше .. Спасибо – Nick

 Смежные вопросы

  • Нет связанных вопросов^_^