给定层次结构中的任何 ID,获取自引用表中的整个 ID 链

发布于 2024-11-15 00:59:00 字数 549 浏览 4 评论 0原文

我有一个包含以下数据的表:

+----+----------+
| ID | ParentID |
+----+----------+
| 27 |    0     |
| 38 |    27    | 
| 45 |    38    |
| 86 |    0     |
| 92 |    45    |
| 48 |    86    |
| 62 |    92    |
| 50 |    62    |
-----------------

我希望能够将任何 ID 传递给存储过程并获取整个 该给定 ID 的 ID 链(父级和子级)。

IE。如果我通过 ID = 45,我应该得到:

27
38
45
92
62
50

同样,如果我通过 ID = 86,我应该得到:

86
48

任何帮助将不胜感激!

I have a table that contains the following data:

+----+----------+
| ID | ParentID |
+----+----------+
| 27 |    0     |
| 38 |    27    | 
| 45 |    38    |
| 86 |    0     |
| 92 |    45    |
| 48 |    86    |
| 62 |    92    |
| 50 |    62    |
-----------------

I would like to be able to pass any ID to a stored procedure and get the entire chain of IDs (parents and children) of that given ID.

ie. if I pass ID = 45, I should get:

27
38
45
92
62
50

Similarly, if I pass ID = 86, I should get:

86
48

Any help would be greatly appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白日梦 2024-11-22 00:59:00

您可以使用两个递归 CTE。第一个找到根节点,第二个构建链。

declare @T table(ID int, ParentID int)

insert into @T values (27,  0), (38, 27), (45, 38), (86,  0),
                      (92, 45), (48, 86), (62, 92), (50, 62)    

declare @ID int = 45

;with cte1 as
(
  select T.ID, T.ParentID, 1 as lvl
  from @T as T
  where T.ID = @ID
  union all
  select T.ID, T.ParentID, C.lvl+1
  from @T as T
    inner join cte1 as C
      on T.ID = C.ParentID
),
cte2 as
(
  select T.ID, T.ParentID
  from @T as T
  where T.ID = (select top 1 ID
                from cte1
                order by lvl desc)
  union all
  select T.ID, T.ParentID
  from @T as T
    inner join cte2 as C
      on T.ParentID = C.ID
)
select ID
from cte2

版本 2

更短一些,查询计划建议更有效,但如果不测试真实数据,你永远不会知道。

;with cte as
(
  select T.ID, T.ParentID, ','+cast(@ID as varchar(max)) as IDs
  from @T as T
  where T.ID = @ID
  union all
  select T.ID, T.ParentID, C.IDs+','+cast(T.ID as varchar(10))
  from @T as T
    inner join cte as C
      on (T.ID = C.ParentID or
          T.ParentID = C.ID) and
          C.IDs+',' not like '%,'+cast(T.ID as varchar(10))+',%'
)
select ID
from cte

You can use two recursive CTE's. The first finds the root node and the second builds the chain.

declare @T table(ID int, ParentID int)

insert into @T values (27,  0), (38, 27), (45, 38), (86,  0),
                      (92, 45), (48, 86), (62, 92), (50, 62)    

declare @ID int = 45

;with cte1 as
(
  select T.ID, T.ParentID, 1 as lvl
  from @T as T
  where T.ID = @ID
  union all
  select T.ID, T.ParentID, C.lvl+1
  from @T as T
    inner join cte1 as C
      on T.ID = C.ParentID
),
cte2 as
(
  select T.ID, T.ParentID
  from @T as T
  where T.ID = (select top 1 ID
                from cte1
                order by lvl desc)
  union all
  select T.ID, T.ParentID
  from @T as T
    inner join cte2 as C
      on T.ParentID = C.ID
)
select ID
from cte2

Version 2

A bit shorter and query plan suggests more effective but you never know without testing on real data.

;with cte as
(
  select T.ID, T.ParentID, ','+cast(@ID as varchar(max)) as IDs
  from @T as T
  where T.ID = @ID
  union all
  select T.ID, T.ParentID, C.IDs+','+cast(T.ID as varchar(10))
  from @T as T
    inner join cte as C
      on (T.ID = C.ParentID or
          T.ParentID = C.ID) and
          C.IDs+',' not like '%,'+cast(T.ID as varchar(10))+',%'
)
select ID
from cte
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文