Tsql 如何使用t-SQL获取表中树数据的所有父级

Tsql 如何使用t-SQL获取表中树数据的所有父级,tsql,sap-ase,Tsql,Sap Ase,我有一个包含树数据的表,如sybase ASE 12.5: mytab(id、pid、名称、isleaf等) isleaf将行标记为叶或不在树中 假设现在我有3个叶子节点(行)。然后我想得到这3个节点的所有父节点。 如何在一个t-sql中获得结果 示例数据如下: | ID | Name | PID | |----|-------------------|------------| | 1 | Dashboard | 0

我有一个包含树数据的表,如sybase ASE 12.5: mytab(id、pid、名称、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       

下面是一种基于循环的方法,有望与多种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]

你能解释一下你是如何从
pid=31
开始得到这个结果的吗?
iseaf
字段在哪里?哎呀,我不知道SYBASE不支持它们。
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]