упорядочить иерархические данные в дереве с помощью ROW_NUMBER или это должно быть сделано с помощью цикла? - PullRequest
1 голос
/ 16 июля 2009

У меня есть набор иерархических данных, которые я надеюсь получить в нужном формате без использования цикла. Может быть, это долгий день, и я просто не понимаю, как это сделать.

При запуске данные выглядят так: (строка = идентификатор строки, par = идентификатор родительской строки, lev = уровень, has_child очевидна, пришлось это сделать или отредактировать пробел между всеми этими числами!)

row par lev has_child
1   NUL 0   1
2   1   1   1
3   1   1   1
4   1   1   1
5   1   1   1
6   1   1   0
148 2   2   0
149 2   2   1
145 3   2   0
146 3   2   1
9   4   2   0
11  4   2   0
12  4   2   0
13  4   2   0
14  4   2   0
15  4   2   0
16  4   2   0
17  4   2   0

Я бы хотел, чтобы это был родитель, ребенок, ребенок, ребенок, ... порядок. Таким образом, все дочерние элементы родительского элемента отображаются до запуска следующего родительского элемента. Как это:

Parent
  |
   --- child L1
       | 
       ---- child L2
       | 
       ----- child L2 
           |
           ---- child L3 
       |
       ----- child L2 
  | 
  ---- child L1 

Кажется, что я должен быть в состоянии сделать это, используя ROW_NUMBER (), но я возился с этим в течение хороших получасов без удачи. Должен ли я сделать это в цикле?

Ответы [ 2 ]

3 голосов
/ 16 июля 2009

Вы не можете с ROW_NUMBER (). Вам нужно использовать рекурсивный CTE и создать синтетический порядок сортировки, составив полный родительский путь:

declare @table table (row int, par int, lev int, has_child bit);

insert into @table 
select 1, NULL, 0, 1
union all select 2,   1,   1,       1
union all select 3,   1,   1,       1
union all select 4,   1,   1,       1
union all select 5,   1,   1,       1
union all select 6,   1,   1,       0
union all select 148, 2,   2,       0
union all select 149, 2,   2,       1
union all select 145, 3,   2,       0
union all select 146, 3,   2,       1
union all select 9,   4,   2,       0
union all select 11,  4,   2,       0
union all select 12,  4,   2,       0
union all select 13,  4,   2,       0
union all select 14,  4,   2,       0
union all select 15,  4,   2,       0
union all select 16,  4,   2,       0
union all select 17,  4,   2,       0;

with cte_anchor as (
  select row, par, 0 as lev, cast(row as varchar(max)) as wbs
     from @table
     where par is null)
, cte_recursive as (
  select row, par, lev, wbs
  from cte_anchor
  union all
  select  t.row, t.par, r.lev+1 as lev
    , r.wbs + '.' + cast(t.row as varchar(max)) as wbs
  from @table t
  join cte_recursive r on t.par = r.row)
select * from cte_recursive
order by wbs
0 голосов
/ 16 июля 2009

У меня есть пример по этому вопросу (который сложнее, но вы поймете)

Иерархия дерева SQL Server и вложенные наборы с идентификаторами повторяющихся записей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...