【问题标题】:Recursive Child/Parent queries in T/SQLT/SQL 中的递归子/父查询
【发布时间】:2024-05-21 00:35:01
【问题描述】:

我在 Microsoft SQL Server 2008 中使用 T/SQL

我有一张桌子

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

它有正确的世代,但排序顺序错误! 有谁知道如何解决这个问题?

谢谢!

【问题讨论】:

    标签: sql-server-2008 tsql recursion


    【解决方案1】:

    你还需要你的递归来构建一些可以在最后排序的东西:

    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 类型用于这种事情......

    【讨论】:

    【解决方案2】:

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

    【讨论】:

      最近更新 更多