我有一个像sybase ASE 12.5一样的树数据表: mytab(id,pid,name,isleaf,....)
isleaf将行标记为树或不在树中。
假设现在我有3个叶子节点(行)。然后我想获得这3个节点的所有父节点。 如何在一个单独的t-sql中获得结果?
示例数据如:
| ID | Name | PID |
|----|-------------------|------------|
| 1 | Dashboard | 0 |
| 2 | Content | 0 |
| 3 | Modules | 0 |
| 4 | Users | 0 |
| 5 | Settings | 0 |
| 6 | Reports | 0 |
| 7 | Help | 0 |
| 8 | Pages | 2 |
| 9 | Media | 2 |
| 10 | Articles | 2 |
| 11 | Menues | 2 |
| 12 | Templates | 2 |
| 13 | Themes | 2 |
| 14 | Blog | 2 |
| 15 | Forum | 2 |
| 16 | Core Modules | 3 |
| 17 | User Modules | 3 |
| 18 | All Users | 4 |
| 19 | Groups | 4 |
| 20 | Permissions | 4 |
| 21 | Import and Export | 4 |
| 22 | Send Email | 4 |
| 23 | Login Records | 4 |
| 24 | General Settings | 5 |
| 25 | Email Settings | 5 |
| 26 | Popular Content | 6 |
| 27 | Most Active Users | 6 |
| 28 | Documentation | 7 |
| 29 | About | 7 |
| 30 | Products | 17 |
| 31 | Categories | 17 |
假设pid = 31是叶子。我希望得到如下结果:
ID | Name | PID
------------------------
3 | Modules | 0
17 | User Modules | 3
答案 0 :(得分:1)
这是一种基于循环的方法,希望能够与各种T-SQL实现一起使用:
if (object_id('tempdb..#NodeTree') is not null)
drop table #NodeTree
create table #NodeTree (BaseID int, BaseName varchar(100), ParentID int, ParentName varchar(100), [Level] int)
if (object_id('tempdb..#Leaves') is not null)
drop table #Leaves
select row_number() over (order by ID) RowNum, n.*
into #Leaves
from Nodes n
where IsLeaf = 1
declare @max int = @@rowcount
declare @rowNumIndex int = 1
declare @baseId int
declare @baseName varchar(100)
declare @parentId int = 0
declare @parentName varchar(100)
while (@rowNumIndex <= @max)
begin
declare @grandpa int = 0
declare @level int = 0
insert into #NodeTree
select l.ID, l.Name, l.PID, l.Name, @level
from #Leaves l
where l.RowNum = @rowNumIndex
select @baseId = l.ID, @baseName = l.Name,
@parentId = n.PID, @parentName = n.Name, @grandpa = n.PID
from #Leaves l
join Nodes n
on l.PID = n.ID
where l.RowNum = @rowNumIndex
if (@@rowcount > 0)
begin
set @level += 1
insert into #NodeTree
values (@baseId, @baseName, @parentId, @parentName, @level)
end
while (@grandpa > 0)
begin
set @level += 1
select @parentId = n.PID, @parentName = n.Name, @grandpa = isnull(n2.ID, 0)
from Nodes n
left join Nodes n2
on n.PID = n2.ID
where n.ID = @grandpa
insert into #NodeTree
values (@baseId, @baseName, @parentId, @parentName, @level)
end
set @rowNumIndex += 1
end
select *
from #NodeTree
order by BaseID, [Level]
这是一种递归CTE方法,适用于某些T-SQL实现,如MS SQL Server 2005及更高版本:
with NodePaths as
(
select ID, Name, PID, ID BaseID, Name BaseName, 0 [Level]
from Nodes
where IsLeaf = 1
union all
select n.ID, n.Name, n.PID, np.BaseID, np.BaseName, np.[Level] + 1
from Nodes n
join NodePaths np
on np.PID = n.ID
)
select BaseID, BaseName, PID ParentId, Name ParentName, [Level]
from NodePaths
order by BaseID, [Level]