首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL Server CTE选择单树分支结构直到根

SQL Server CTE选择单树分支结构直到根
EN

Stack Overflow用户
提问于 2011-12-22 17:39:32
回答 2查看 7.9K关注 0票数 6

有没有可能把一个参数传递给CTE,让它选择一个节点,然后选择它的父节点,直到parentId为null的根?

在下面的代码中,如果我传入一个选择Rain Coats的参数,然后在树中向上递归到mens where,其中它的parentId为null,并选择该分支中的所有节点,包括子节点。有人能帮我拿一下这个吗?我的示例只是递归并显示了深度

SQL示例:

代码语言:javascript
复制
DECLARE @Department TABLE
(
    Id INT NOT NULL,
    Name varchar(50) NOT NULL,
    ParentId int NULL
)

INSERT INTO @Department SELECT 1, 'Toys', null
INSERT INTO @Department SELECT 2, 'Computers', null
INSERT INTO @Department SELECT 3, 'Consoles', 2
INSERT INTO @Department SELECT 4, 'PlayStation 3', 3
INSERT INTO @Department SELECT 5, 'Xbox 360', 2
INSERT INTO @Department SELECT 6, 'Games', 1
INSERT INTO @Department SELECT 7, 'Puzzles', 6
INSERT INTO @Department SELECT 8, 'Mens Wear', null
INSERT INTO @Department SELECT 9, 'Mens Clothing', 8
INSERT INTO @Department SELECT 10, 'Jackets', 9
INSERT INTO @Department SELECT 11, 'Rain Coats', 10

;WITH c 
AS
(
    SELECT Id, Name,1 AS Depth
    FROM @Department
    WHERE ParentId is null  

         UNION ALL

         SELECT t.Id, t.Name, c.Depth + 1 AS 'Level'
    FROM @Department T  
    JOIN c ON t.ParentId = c.Id

)
SELECT * FROM c WHERE c.Id = 3
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-22 17:46:02

您当前的CTE只显示树中的所有项,以及它们的Depth和所有其他属性。因此,它工作得很好。

要做你想做的事情,你必须几乎“颠倒”CTE --首先抓取你感兴趣的项目,作为你的CTE的“锚”,然后“递归”到根:

代码语言:javascript
复制
DECLARE @StartID INT = 11

;WITH c 
AS
(
    SELECT Id, ParentId, Name, 1 AS Depth
    FROM @Department
    WHERE Id = @startID

    UNION ALL

    SELECT t.Id, t.ParentId, t.Name, c.Depth + 1 AS 'Level'
    FROM @Department T  
    INNER JOIN c ON t.Id = c.ParentId
)
SELECT * 
FROM c 

这将会做你想要做的事情并输出:

代码语言:javascript
复制
Id ParentId  Name            Depth
11    10     Rain Coats        1
10     9     Jackets           2
 9     8     Mens Clothing     3
 8   NULL    Mens Wear         4

更新

对于深度的逆序,您可以使用以下命令:

代码语言:javascript
复制
;WITH c 
AS
(
    SELECT Id, ParentId, Name, 1 AS Depth
    FROM @Department
    WHERE Id = @startID

    UNION ALL

    SELECT t.Id, t.ParentId, t.Name, c.Depth + 1 AS 'Level'
    FROM @Department T  
    INNER JOIN c ON t.Id = c.ParentId
)
SELECT Id,
       ParentID, 
       Name,
       MAX(Depth) OVER() - Depth + 1 AS InverseDepth
FROM c

下面的输出:

代码语言:javascript
复制
Id ParentId  Name            InverseDepth
11    10     Rain Coats        4
10     9     Jackets           3
 9     8     Mens Clothing     2
 8   NULL    Mens Wear         1
票数 15
EN

Stack Overflow用户

发布于 2011-12-22 17:49:04

目前,您的CTE具有作为其锚的根,并且在其递归部分中从父到子。如果你想要整棵树,你需要从感兴趣的孩子开始,然后往上走。这是实现这一目标的一种方法。我引入了一个新的列StartingId,它在我们遍历树时保持不变-这是我们将根据以下条件选择的列:

代码语言:javascript
复制
;WITH c 
AS
(
    SELECT Id AS StartingId, Id, ParentId, Name, 0 AS Height
    FROM @Department

    UNION ALL

    SELECT c.StartingId, p.Id, p.ParentId, p.Name, c.Height + 1 AS Height
    FROM @Department p INNER JOIN c ON p.Id = c.ParentId
)
SELECT * FROM c WHERE c.StartingId = 11

给出

代码语言:javascript
复制
StartingId  Id          ParentId    Name                                   Height
----------- ----------- ----------- ----------------------------------------------
11          11          10          Rain Coats                             0
11          10          9           Jackets                                1
11          9           8           Mens Clothing                          2
11          8           NULL        Mens Wear                              3
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8601965

复制
相关文章

相似问题

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