首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Server 2008 -获取底部链接最多的记录

Server 2008 -获取底部链接最多的记录
EN

Stack Overflow用户
提问于 2017-04-14 10:49:03
回答 2查看 645关注 0票数 0

我的Server数据库中有以下数据:

代码语言:javascript
复制
Id | Name | LinkedId
---+------+----------
1  | A    | 1
2  | B    | 2
3  | C    | 1
4  | D    | 3
5  | E    | 4

现在,我想编写一个存储过程,其中应该显示以下记录:

注意事项LinkedId具有与该名称相关联的Id。

例如,:"C“与"A”相关联

代码语言:javascript
复制
Id | Name | LinkedId
---+------+---------
1  | A    | 1
2  | B    | 2
3  | C    | 1
4  | D    | 1 //here instead of showing 3, it showed 1 which is the bottom most value in the tree
5  | E    | 1 //same case as the above

问题

对于这种情况,根据我有限的知识,我只能考虑使用联接(左,内),但在这种情况下,这还不足以获得最底层的链接id。

编辑(输出):

我希望所有与"C“项直接或间接关联的项目

代码语言:javascript
复制
Id | Name | 
---+------+
3  | C    | 
4  | D    | 
5  | E    | 
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-14 11:01:40

您可以使用递归函数。

使用CTE的一个简单的解释递归函数是一个用于计算的common table expression。它包括:

  1. 调用例程。

递归CTE的第一次调用包括一个或多个CTE_query_definitions,由UNION、UNION、of或INTERSECT加入。

由于这些查询定义构成CTE结构的基本结果集,因此它们被称为锚成员。

CTE_query_definitions被认为是锚点成员,除非它们引用CTE本身。

所有锚成员查询定义必须位于第一个递归成员定义之前,并且必须使用UNION操作符将最后一个锚成员与第一个递归成员连接起来。

  1. 例程的递归调用。

递归调用包括一个或多个CTE_query_definitions,由引用CTE本身的UNION操作符加入。这些查询定义称为递归成员。

  1. 终止支票。

终止检查是隐式的;当上次调用没有返回任何行时,递归将停止。

参考链接:使用CTE的递归查询

递归CTE的简单实例 Cte sql服务器

代码语言:javascript
复制
DECLARE @SampleData AS TABLE (Id int, Name varchar(10), LinkedId int)

INSERT INTO @SampleData 
VALUES (1, 'A', 1), (2, 'B', 2), 
(3, 'C', 1),(4, 'D', 3),(5, 'A', 4)

;WITH temp AS 
(
   SELECT sd.Id, sd.Name,  sd.Id AS RootId 
   FROM @SampleData sd WHERE sd.LinkedId = sd.Id -- Invocation of the routine, in this case it's root node of tree.

   UNION ALL
   -- Recursive invocation of the routine
   SELECT sd.Id, sd.Name,  t.RootId AS RootId  
   FROM temp t
   INNER JOIN @SampleData sd ON sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id
   -- Termination check: sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id. 
   -- It make recursive query is not an infinitive loop
)
SELECT  t.Id, t.Name, t.RootId AS LinkedId
FROM temp t
OPTION (MAXRECURSION 0) -- this option remove recursive max depth, default is 100.

演示链接:雷克斯试验器

对于新输出,可以更改The first invocation of the recursive CTE

代码语言:javascript
复制
;WITH temp AS 
(
   SELECT sd.Id, sd.Name,  sd.Id AS RootId 
   FROM @SampleData sd WHERE sd.Id = 3

   UNION ALL
   -- Recursive invocation of the routine
   SELECT sd.Id, sd.Name,  t.RootId AS RootId  
   FROM temp t
   INNER JOIN @SampleData sd ON sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id
   -- Termination check: sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id. 
   -- It make recursive query is not an infinitive loop
)
SELECT  t.Id, t.Name, t.RootId AS LinkedId
FROM temp t
OPTION (MAXRECURSION 0) -- this option remove recursive max depth, default is 100.
票数 2
EN

Stack Overflow用户

发布于 2017-04-14 10:54:24

您需要一个递归过程:

代码语言:javascript
复制
with cte as (
      select t.id, t.name, t.linkedid, 1 as lev
      from t
      where t.linkedid = t.id
      union all
      select t.id, t.name, cte.linkedid, cte.lev + 1
      from t join
           cte
           on cte.id = t.linkedid and t.linkedid <> t.id
     )
select id, name, linkedid
from cte;

这里是在实践中起作用的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43410040

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档