2011-12-22 50 views
5

是否有可能一个参数传递到的CTE选择节点然后选择它的父到根,其中parentId为空?SQL Server的CTE选择单树枝结构高达根

在我的代码下面,如果我传入一个参数,选择雨衣,然后递归上树到男士穿其parentId为空,并选择该分支中的所有节点,包括儿童。请有人可以帮我解决这个问题。我的例子只是递归,显示深度

SQL例如:

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 
+0

什么是您目前的查询和输出你想要什么?我不明白你想要的东西还没有在那个查询中。 – 2011-12-22 09:42:28

+0

我想在其选择的节点的参数传递,然后遍历了树,以它的根在该分支与所有的孩子 – ONYX 2011-12-22 09:44:11

+0

所以,如果我选择雨衣我想要的程序去向上和选择所有家长到该节点高达意味着在父母为零的情况下佩戴,因此这将包括所有孩子都有意义 – ONYX 2011-12-22 09:46:54

回答

13

您当前的CTE只显示了树中的所有项目,他们Depth和所有其他属性。因此,它工作正常。

要做你正在寻找的东西,你必须几乎“反转”CTE - 先抓住你感兴趣的物品,作为你的CTE的“锚点”,然后“递增”到根:

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 

这会做你要找的输出内容:

Id ParentId Name   Depth 
11 10  Rain Coats  1 
10  9  Jackets   2 
9  8  Mens Clothing  3 
8 NULL Mens Wear   4 

更新

深度的逆序你ç一个使用本:从这个

;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 

输出:

Id ParentId Name   InverseDepth 
11 10  Rain Coats  4 
10  9  Jackets   3 
9  8  Mens Clothing  2 
8 NULL Mens Wear   1 
+0

如何以相反的顺序改变深度它倒退男士穿着是1-4雨衣。并且这样做是否选择所有的子节点都会影响每个节点 – ONYX 2011-12-22 09:50:07

+0

@KDM:你是什么意思*选择每个节点下的所有子节点*?你从一个给定的节点走了树 - 每个节点总是有且只有一个父节点,这就是被选中 – 2011-12-22 09:52:42

+0

@KDM - 您可以在主要使用'ROW_NUMBER()以上(按深度递减顺序)Depth'查询。 – 2011-12-22 09:53:26

4

目前,您的CTE有根作为其锚,和父母去孩子的递归部分。如果你想要整棵树,你需要从感兴趣的孩子开始,然后继续前进。这是做到这一点的一种方法。我已经介绍了新列StartingId当我们走了树,保持不变 - 这就是我们将选择基于:

;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 

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