示例问题如下:
表结构:
IdParentId
10
21
32
......
针对该表结构解释如下:
1的父节点为0,
2的父节点为1,
3的父节点为2
......
以此类推,要求给定一个父节点的值,比如1,
用SQL语句查询的到该父结点下的所有子节点
下面的Sql是在SqlServer下调试通过的,如果是Oracle,则有ConnectBy可以实现.
建立测试表:
DropTableDbTree
CreateTableDbTree
(
[Id]Int,
[Name]NVarChar(20),
[ParentId]Int
)
插入测试数据:
InsertIntoDbTree([Id],[ParentId])Values(1,0)
InsertIntoDbTree([Id],[ParentId])Values(2,1)
InsertIntoDbTree([Id],[ParentId])Values(3,1)
InsertIntoDbTree([Id],[ParentId])Values(4,3)
InsertIntoDbTree([Id],[ParentId])Values(5,4)
InsertIntoDbTree([Id],[ParentId])Values(6,7)
InsertIntoDbTree([Id],[ParentId])Values(8,5)
实现方法一:
代码如下:
Declare@IdInt
Set@Id=1---在次修改父节点
Select*Into#TempFromDbTreeWhereParentIdIn(@Id)
Select*Into#AllRowFromDbTreeWhereParentIdIn(@Id)--1,2
WhileExists(Select*From#Temp)
Begin
Select*Into#Temp2From#Temp
TruncateTable#Temp
InsertInto#TempSelect*FromDbTreeWhereParentIdIn(SelectIdFrom#Temp2)
InsertInto#AllRowSelect*From#Temp
DropTable#Temp2
End
Select*From#AllRowOrderById
DropTable#Temp
DropTable#AllRow
实现方法二:
代码如下:
CreateTable#AllRow
(
IdInt,
ParentIdInt
)
Declare@IdInt
Set@Id=1---在次修改父节点
Delete#AllRow
--顶层自身
InsertInto#AllRow(Id,ParentId)Select@Id,@Id
While@@RowCount>0
Begin
InsertInto#AllRow(Id,ParentId)
SelectB.Id,A.Id
From#AllRowA,DbTreeB
WhereA.Id=B.ParentIdAnd
NotExists(SelectIdFrom#AllRowWhereId=B.IdAndParentId=A.Id)
End
DeleteFrom#AllRowWhereId=@Id
Select*From#AllRowOrderById
DropTable#AllRow
实现方法三:
代码如下:
在SqlServer2005中其实提供了CTE[公共表表达式]来实现递归:
关于CTE的使用请查MSDN
Declare@IdInt
Set@Id=3;---在次修改父节点
WithRootNodeCTE(Id,ParentId)
As
(
SelectId,ParentIdFromDbTreeWhereParentIdIn(@Id)
UnionAll
SelectDbTree.Id,DbTree.ParentIdFromRootNodeCTE
InnerJoinDbTree
OnRootNodeCTE.Id=DbTree.ParentId
)
Select*FromRootNodeCTE