数据表中遍历寻找子节点的三种实现方法

        以前公司的同事在QQ上发了个面试题过来,让我给看看.这个问题的巧妙实现,
几年前在一个很出名的Delphi论坛上见过.
感觉里面蕴含有很多SQL的技巧,所以整理了一下,希望对大家有帮助吧!

问题如下:

有表结构如下:
 Id  ParentId
 1  0
 2  1
 3  2
 ......
针对该表结构解释如下:
1的父节点为0,
2的父节点为1,
3的父节点为2
......
以此类推,要求给定一个父节点的值,比如1,
用SQL语句查询的到该父结点下的所有子节点


如下的Sql是在Sql Server下调试通过的,如果是Oracle,则有Connect By可以实现.

建立测试表:

Drop   Table  DbTree
Create   Table  DbTree
(
        
[ Id ]   Int ,
        
[ Name ]   NVarChar ( 20 ),
        
[ ParentId ]   Int
)

插入测试数据:

Insert   Into  DbTree ( [ Id ] , [ ParentId ] Values  ( 1 , 0 )
Insert   Into  DbTree ( [ Id ] , [ ParentId ] Values  ( 2 , 1 )
Insert   Into  DbTree ( [ Id ] , [ ParentId ] Values  ( 3 , 1 )
Insert   Into  DbTree ( [ Id ] , [ ParentId ] Values  ( 4 , 3 )
Insert   Into  DbTree ( [ Id ] , [ ParentId ] Values  ( 5 , 4 )
Insert   Into  DbTree ( [ Id ] , [ ParentId ] Values  ( 6 , 7 )
Insert   Into  DbTree ( [ Id ] , [ ParentId ] Values  ( 8 , 5 )

实现方法一:
代码如下:

Declare   @Id   Int
Set   @Id   =   1          -- -在次修改父节点
Select   *   Into  # Temp     From  DbTree  Where  ParentId  In  ( @Id
Select   *   Into  #AllRow  From  DbTree  Where  ParentId  In  ( @Id -- 1,2

While   Exists ( Select   *   From  # Temp )
Begin
    
Select   *   Into  #Temp2  From  # Temp
    
Truncate   Table  # Temp

    
Insert   Into  # Temp      Select   *   From  DbTree  Where  ParentId  In  ( Select  Id  From  #Temp2)
    
Insert   Into  #AllRow   Select   *   From  # Temp
    
Drop   Table  #Temp2
End
Select   *   From  #AllRow  Order   By  Id

Drop   Table  # Temp
Drop   Table  #AllRow

实现方法二:
代码如下:

Create   Table  #AllRow
(
    Id  
Int
    ParentId 
Int


Declare   @Id   Int
Set   @Id   =   1          -- -在次修改父节点

Delete  #AllRow

-- 顶层自身
Insert   Into  #AllRow (Id,ParentId)  Select   @Id ,   @Id

While   @@RowCount   >   0
Begin
    
Insert   Into  #AllRow (Id,ParentId)
    
Select  B.Id,A.Id
    
From  #AllRow A,DbTree B
    
Where  A.Id  =  B.ParentId  And
    
Not   Exists  ( Select  Id  From  #AllRow  Where  Id  =  B.Id  And  ParentId  =  A.Id)
End  

Delete   From  #AllRow  Where  Id  =   @Id
Select   *   From  #AllRow  Order   By  Id
Drop   Table  #AllRow

实现方法三:
代码如下:

在Sql Server2005中其实提供了CTE[公共表表达式]来实现递归:
关于CTE的使用请查MSDN

Declare   @Id   Int
Set   @Id   =   3 ;     -- -在次修改父节点

With  RootNodeCTE(Id,ParentId)
As
(
    
Select  Id,ParentId  From  DbTree  Where  ParentId  In  ( @Id )
    
Union   All
    
Select  DbTree.Id,DbTree.ParentId  From  RootNodeCTE
    
Inner   Join  DbTree
    
On  RootNodeCTE.Id  =  DbTree.ParentId
)

Select   *   From  RootNodeCTE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值