【问题标题】:Get Root parent of child in Hierarchical table在层次表中获取孩子的根父级
【发布时间】:2014-07-02 05:35:39
【问题描述】:

我有一个包含分层数据的表,结构如下:

ID      ParentId
----   ----------
1       NULL
2       1
3       2
4       2
5       3
6       5

如果我传递节点 ID,我想通过在 SQL 中遍历其所有父节点来获取最高节点 ID/详细信息。

我尝试了 CTE,但我无法正确组合。然而,我把它作为一个函数工作,但它太慢了,我不得不发布这个问题。

在上面的示例中,如果我通过 6,我希望获得最高的值,即 1。通过遍历 6 => 5 => 3 => 2 => [1](结果)

提前感谢您的帮助。

【问题讨论】:

  • CTE 是公用表表达式。

标签: sql sql-server sql-server-2008 sql-server-2008-r2


【解决方案1】:
DECLARE @id INT = 6
;WITH parent AS
(
    SELECT id, parentId, 1 AS [level] from tbl WHERE id = @id
    UNION ALL 
    SELECT t.id, t.parentId, [level] + 1 FROM parent
    INNER JOIN tbl t ON t.id =  parent.parentid
)
SELECT TOP 1 id FROM parent ORDER BY [level] DESC

@TechDo 的回答假定最低 ID 将是父级。如果你不想依赖这个,那么上面的查询将按深度排序。

【讨论】:

  • 这应该是公认的答案。如果根的 id 更高(这是一种常见情况),TechDos 的答案将给出错误的结果
  • 有没有办法扩展这个来获取每个id的根父id
  • @AvinKavish 如果我理解正确的话,我认为您可以使用上述查询创建一个函数,然后在您自己的查询中使用该函数来获取每个 ID 的根 ID。
【解决方案2】:

请尝试:

declare @id int=6
;WITH parent AS
(
    SELECT id, parentId  from tbl WHERE id = @id
    UNION ALL 
    SELECT t.id, t.parentId FROM parent
    INNER JOIN tbl t ON t.id =  parent.parentid
)

SELECT TOP 1 id FROM  parent
order by id asc

【讨论】:

  • 这不是假设根 id 是树的最低 id 吗?如果根 id 的 id 比 oder 节点高怎么办?
【解决方案3】:

你可以试试这个查询我的朋友来获取所有的 id:

with tab1(ID,Parent_ID) as
(select * from table1 where id = 6
union all
select t1.* from table1 t1,tab1 
where tab1.Parent_ID = t1.ID)
select ID from tab1;

这个查询会给出最终结果:

with tab1(ID,Parent_ID) as
(select * from table1 where id = 6
union all
select t1.* from table1 t1,tab1 
where tab1.Parent_ID = t1.ID)
select ID from tab1 where parent_id is null;

SQL Fiddle

【讨论】:

    【解决方案4】:
    ;WITH CTE
    as
    (
        Select I.ID,P.Parent_id
        from #temp I 
        join #temp P 
        on P.Id = I.Parent_Id
        where i.ID = 6
        union all
        Select I.ID,P.Parent_id
        from CTE I 
        join #temp P 
        on P.Id = I.Parent_Id
        where p.Parent_Id is not null
    )
    Select ID,min(parent_id) from CTE group by id;
    

    【讨论】:

      【解决方案5】:
       WITH CTE_MyTable AS (
          SELECT        Id, ParentId, NULL As RootParent, 1 As Lvl
          FROM            dbo.MyTable
          UNION ALL
          SELECT        a.id, b.ParentId, a.ParentId As RootParent, Lvl + 1
          FROM            CTE_MyTable a INNER JOIN
                                                     dbo.MyTable b ON a.ParentId = b.Id
      )
      , CTE_MyTable_RN AS  (
          SELECT Id, RootParent, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Lvl DESC) RN
          FROM CTE_MyTable
      )
      
      SELECT Id, ISNULL(RootParent, Id) As RootParent
      FROM CTE_MyTable_RN
      WHERE RN = 1
      

      【讨论】:

        猜你喜欢
        • 2016-03-13
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多