Рекурсивные дочерние / родительские запросы в T / SQL - PullRequest
3 голосов
/ 25 января 2012

Я использую T / SQL в Microsoft SQL Server 2008

У меня есть стол

CREATE TABLE [TestTable](
[CHILD] [int] NOT NULL,
[PARENT] [int] NOT NULL
) ON [PRIMARY]

GO

Это некоторые значения, которые определяют родительские дочерние иерархические отношения

CHILD PARENT
1       2
2       0
3       1
4       2
5       0

Визуально эта таблица выглядит следующим образом

0
   2
      1
         3
      4
   5

В идеале мне бы хотелось, чтобы значения отображались следующим образом (где правая колонка указывает поколение)

CHILD    GENERATION
 0          0
 2          1
 1          2
 3          3
 4          2
 5          1

Мой код T / SQL выглядит следующим образом

with n(CHILD, PARENT, GENERATION) as (
select CHILD, PARENT,1 as GENERATION from TestTable
where PARENT=0 
union all
select nplus1.CHILD, nplus1.PARENT, GENERATION+1 from TestTable as nplus1, n
where nplus1.PARENT=n.CHILD 
)
select CHILD,GENERATION from n

Однако это не работает!

Возвращает

CHILD   GENERATION
2        1
5        1
1        2
4        2
3        3

У него правильное поколение, но неправильный порядок сортировки! У кого-нибудь есть идеи как это решить?

Спасибо!

Ответы [ 2 ]

6 голосов
/ 25 января 2012

Вам понадобится ваша рекурсия, чтобы также построить что-то, что можно отсортировать в конце:

declare @t TABLE (
[CHILD] [int] NOT NULL,
[PARENT] [int] NOT NULL
) 

insert @t values
( 0, -1),   -- I added this
( 1, 2 ),
( 2, 0 ),
( 3, 1 ),
( 4, 2 ),
( 5, 0 )

(обратите внимание, я добавил истинный корневой элемент)

;with n(CHILD, PARENT, GENERATION, hierarchy) as (
select CHILD, PARENT,0, CAST(CHILD as nvarchar) as GENERATION from @t
where PARENT=-1
union all
select nplus1.CHILD, nplus1.PARENT, GENERATION+1, 
cast(n.hierarchy + '.' + CAST(nplus1.child as nvarchar) as nvarchar)
 from 
@t as nplus1 inner join n on nplus1.PARENT=n.CHILD 
)
select CHILD,GENERATION
from n
order by hierarchy

возвращает

CHILD       GENERATION
----------- -----------
0           0
2           1
1           2
3           3
4           2
5           1

Включая hierarchy для иллюстрации:

CHILD       GENERATION  hierarchy
----------- ----------- ------------------------------
0           0           0
2           1           0.2
1           2           0.2.1
3           3           0.2.1.3
4           2           0.2.4
5           1           0.5

В зависимости от того, насколько велики ваши идентификаторы, вам, возможно, придется сделать что-то с левым заполнением нулями, чтобы получить правильную сортировку.

Обратите внимание, что в SQL 2008 есть встроенный тип hierarchy для такого рода вещей ...

0 голосов
/ 12 февраля 2015

На основе решения AakashM я предлагаю решение, которое будет несколько более общим, поскольку оно использует row_number для построения иерархии вместо использования значений столбцов.

Вот оно:

;with n(CHILD, PARENT, GENERATION, hierarchy) as (
select CHILD, PARENT,0, CAST(CHILD as nvarchar) as GENERATION from @t
where PARENT=-1
union all
select nplus1.CHILD, nplus1.PARENT, GENERATION+1, 
cast(hierarchy + '.' + CAST(cast(ROW_NUMBER() over (order by nplus1.CHILD) as int) as nvarchar) as nvarchar)
 from 
@t as nplus1 inner join n on nplus1.PARENT=n.CHILD 
)
select CHILD,GENERATION,hierarchy
from n
order by hierarchy

возвращает:

CHILD   GENERATION  hierarchy
0   0   0
2   1   0.1
1   2   0.1.1
3   3   0.1.1.1
4   2   0.1.2
5   1   0.2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...