2012-01-25 66 views
3

我使用T/SQL在Microsoft SQL Server 2008递归父/子查询

我有一个表

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

GO 

这是定义一个父子hierarchial关系

一些值
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 

它拥有权发生,但错误的排序顺序! 有没有人有任何想法如何解决这个问题?

谢谢!

回答

6

你需要你的递归也建立一些可以在年底进行排序:

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 

根据你的id有多大,你可能需要用零填充来填充正确的东西。

请注意,SQL 2008中有一个内置的hierarchy类型这种事情......

+0

非常好的答案三江源。 – gordon613

+0

我也看过http://blogs.msdn.com/b/simonince/archive/2008/10/17/hierarchies-with-hierarchyid-in-sql-2008.aspx,它讨论了您提到的hierarchyID类型。 – gordon613

0

基于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