2

我有一个用于构建菜单项树结构的表。该表的示例内容如下:

Parent      Child
------      ------
190         192
192         180
180         185
185         184
190         191
191         197
197         200

我需要一个查询,它会按照它们在层次结构中出现的顺序(包括子 ID)为我提供一个以逗号分隔的父记录列表,例如:

  • 给定孩子 id 184,它应该返回 190, 192, 180, 185, 184
  • 给定孩子 id 200,它应该返回 190、191、197、200
4

3 回答 3

1

这里是...

Declare @data Table
(
Parent int,
Child int
)

insert into @data values
(190, 192),
(192, 180),
(180, 185),
(185, 184),
(190, 191),
(191, 197),
(197, 200)

Declare @Id as Int = 184

/*

    CompleteData - query produce following output
        ID          ParentId
        ----------- -----------
        180         192
        184         185
        185         180
        190         NULL -- we discoverd this missing data
        191         190
        192         190
        197         191
        200         197

    ChildHierarchyData - query produce following ouput
        ID          ParentID    Level
        ----------- ----------- -----------
        184         185         0
        185         180         1
        180         192         2
        192         190         3
        190         NULL        4

    Concatinated - query conact all ID from above result
*/

;with CompleteData
as
(
    Select Child ID, Parent ParentId from @data
    UNION
    Select Child.Parent Id, Parent.Parent ParentId From @data   Child
        Left Outer Join @data Parent
            on Child.Parent = parent.Child
    WHERE
        parent.Parent IS NULL

),
ChildHierarchyData(ID,ParentID, Level)
as
(
    Select ID,ParentID, 0 as Level from CompleteData Where ID = @Id
    union all
    Select CompleteData.ID, CompleteData.ParentID, ChildHierarchyData.Level +1 from CompleteData 
        INNER Join ChildHierarchyData
            on ChildHierarchyData.ParentID = CompleteData.ID
),
Concatinated(result)
as
(
    Select Cast((select Cast(ID  as nvarchar) + ',' [data()] from ChildHierarchyData Order By Level Desc FOR XML Path('')) as Nvarchar(max))
)
select Left(result, len(result)-1) as Result from Concatinated
于 2013-09-28T03:07:33.000 回答
0

为了演示,我使用了一个表变量。要使用标准表,请删除@tempTable声明和插入语句。然后用@tempTable表名替换引用。

declare @childId int
set @childId = 184

declare @tempTable table(parent int, child int)

insert into @tempTable values(190, 192)
insert into @tempTable values(192, 180)
insert into @tempTable values(180, 185)
insert into @tempTable values(185, 184)
insert into @tempTable values(190, 191)
insert into @tempTable values(191, 197)
insert into @tempTable values(197, 200)

declare @currentItem int
set @currentItem = @childId

declare @output varchar(max)
set @output = cast(@currentItem as varchar)

while (exists(select 1 from @tempTable where child = @currentItem))
begin
    select 
        @currentItem = parent
    from 
        @tempTable 
    where 
        child = @currentItem

    set @output = cast(@currentItem as varchar) + ', ' + @output 
end

select @output

一些示例输出:

对于 184:190, 192, 180, 165, 184

对于 200:190, 191, 197, 200

于 2013-09-28T03:18:35.030 回答
0

如果您需要逗号分隔的列表,使用递归 cte 很容易:

with cte as (
    select
        t.Parent, 1 as Level,
        cast(t.Parent as nvarchar(max)) + ',' + cast(t.Child as nvarchar(max)) as Path
    from Table1 as t
    where t.Child = @Child

    union all

    select
        t.Parent, Level + 1 as Level,
        cast(t.Parent as nvarchar(max)) + ',' + c.Path as Path
    from Table1 as t
        inner join cte as c on c.Parent = t.Child
)
select top 1 Path
from cte
order by Level desc

sql fiddle demo

于 2013-09-28T04:53:47.267 回答