获取根记录'来自自我引用表

时间:2016-03-25 12:10:00

标签: sql sql-server hierarchical-data recursive-query

我有一个自引用表:有一个ID和一个PARENTID列,它允许将记录排序为层次结构(让我们称它们为记录层次结构)。

还有一个查询(让我们称之为“查询A'”),它会返回此表中的记录列表。一些返回的记录是根记录' (PARENTID = NULL),有些是非根记录(PARENTID!= NULL)。请注意,'查询A'可以返回属于同一记录层次结构的多个记录。

我需要以最有效的方式完成(效率很重要,但不是最重要的)是获取'查询A'返回的所有记录的根记录。以便查询A'中的非根记录搜索他们的根记录。

3 个答案:

答案 0 :(得分:1)

可能的解决方案之一:

declare @TableA table
(
  ID int,
  ParentID int NULL,
  Name varchar(100)
)

insert into @TableA(ID, ParentID, Name)
values
(1, NULL, 'root 1'),
(2, NULL, 'root 2'),
(3, 2, 'node 3->2'),
(4, 1, 'node 4->1'),
(5, 4, 'node 5->4->1'),
(6, 3, 'node 6->3->2'),
(7, 4, 'node 7->4->1'),
(8, 7, 'node 8->7->4->1')


;with QueryA as 
(
  /* your query could be here */
  select t.ID, t.Name
  from @TableA t
  where t.ID in (1, 3, 8)
),
Tree as
(
  select t.ID, t.ParentID, t.Name,
    case when t.ParentID is NULL then t.ID end as RootID
  from @TableA t
  /* starting from rows we have in QueryA */
  where t.ID in (select q.ID from QueryA q)

  union all

  select tt.ID, t.ParentID, t.Name,
    case when t.ParentID is NULL then t.ID end as RootID
  from @TableA t
  /* recursion to parents */
  inner join Tree tt on tt.ParentID = t.ID
)
select q.ID, q.Name, t.Name as RootName
from QueryA q
inner join Tree t on t.ID = q.ID and t.RootID is not NULL
order by 1, 2

此外,您可以从构建树开始,而无需链接到QueryA(对于整个表)。会看起来有点简单。在这种情况下,您只能在最终语句中引用QueryA。

答案 1 :(得分:0)

如果您想要检索每个项目的Root项目,那么您可以使用以下方法:

select t1.*,(case when t1.PARENTID is null then t1.ID else t1.PARENTID end ) Id_Root , 0 IsTraced into #tmp
from TableName t1 
left outer join TableName t2 on t1.ID=t1.PARENTID
order by t1.PARENTID

while exists(select TOP 1 * , (select PARENTID  from #tmp where ID=t1.PARENTID) Id_GrandParent from #tmp t1 where IsTraced=0 order by PARENTID desc )
begin
        Declare @CurrentID as uniqueIdentifier
        set @CurrentID = (select TOP 1 ID from #tmp t1 where IsTraced=0 order by PARENTID desc )
        Declare @CurrentParentID as uniqueIdentifier
        set @CurrentParentID = (select TOP 1 PARENTID from #tmp t1 where IsTraced=0 order by PARENTID desc )
        Declare @CurrentGrandParentID as uniqueidentifier
        set @CurrentGrandParentID=(select PARENTID from #tmp where ID=@CurrentParentID)

        if(@CurrentGrandParentID is null)
        begin
            update #tmp set IsTraced=1 where ID=@CurrentID
        end
        else
        begin
            update #tmp set PARENTID= @CurrentGrandParentID, Id_Root=@CurrentGrandParentID  where ID=@CurrentID
        end
end

select ID,Id_Root
from #tmp 
order by PARENTID

正如您在while循环后看到的那样,您可以从ID

中检索每个元素的Id_RootTemp Table #tmp

答案 2 :(得分:0)

这是一个棘手的问题吗?首先,每条记录只有1个父母。并且只有根记录具有空父值。因此,您不必执行任何复杂操作即可获取根记录。

Select * from QueryA where PARENTID is null

在查询引擎的所有记录的真正详尽的搜索 h之后获取所有根记录! PARENTID不为空的所有其他记录不是根记录,它们是定义的子记录。