2016-12-02 41 views
0

我有一个表,让我们说,它看起来是这样的:烦恼递归SQL查询中分离出靶细胞

c | p 
===== 
|1|3| 
|2|1| 
|7|5| 

c代表currentp代表parent

鉴于2我的c值会返回其最顶端的祖先(没有父母),这个值是3。由于这是一个自引用表,我认为使用CTE将是最好的方法,但我对使用它很新颖。不过,我给它一个镜头:

WITH Tree(this, parent) AS 
    (SELECT c ,p 
    FROM myTable 
    WHERE c = '2' 
    UNION ALL 
    SELECT M.c ,M.p 
    FROM myTable M 
    JOIN Tree T ON T.parent = M.c) 
SELECT parent 
FROM Tree 

然而,这将返回:
1
3

我只想3虽然。我试过把WHERE T.parent <> M.c,但这并不完全合理。毫无疑问,我对如何孤立祖父母感到困惑。

+2

你总是想要返回gradparent还是要返回最顶端的祖先?因为前者可以用2个连接完成,而后者将采用递归等技术。顶级父母也总是在表中有记录吗? – Matt

+0

@Matt谢谢你澄清......最顶级的祖先就是我所追求的,没有最顶级的祖先不会有父母。我会更新我的问题。 – 40Alpha

+0

我得到他们将不会有父母,但我想知道是否仍然有故事中的记录,例如子3,父NULL? – Matt

回答

3
DECLARE @Table AS TABLE (Child INT, Parent INT) 
INSERT INTO @Table VALUES (1,3),(2,1),(7,5) 

;WITH cteRecursive AS (
    SELECT 
     OriginalChild = Child 
     ,Child 
     ,Parent 
     ,Level = 0 
    FROM 
     @Table 
    WHERE 
     Child = 2 

    UNION ALL 

    SELECT 
     c.OriginalChild 
     ,t.Child 
     ,t.Parent 
     ,Level + 1 
    FROM 
     cteRecursive c 
     INNER JOIN @Table t 
     ON c.Parent = t.Child 
) 


SELECT TOP 1 TopAncestor = Parent 
FROM 
    cteRecursive 
ORDER BY 
    Level DESC 

使用递归cte来回避树,直到你不能。跟踪递归级别,然后采用递归父级的最后一级,并且您拥有顶级祖先。

只因为我写了它,如果你想找到每个孩子的最高祖先,我会加入。这个概念仍然相同,但您需要引入row_number()来查找递归的最后一个级别。

DECLARE @Table AS TABLE (Child INT, Parent INT) 
INSERT INTO @Table VALUES (1,3),(2,1),(7,5),(5,9) 

;WITH cteRecursive AS (
    SELECT 
     OriginalChild = Child 
     ,Child 
     ,Parent 
     ,Level = 0 
    FROM 
     @Table 

    UNION ALL 

    SELECT 
     c.OriginalChild 
     ,t.Child 
     ,t.Parent 
     ,Level + 1 
    FROM 
     cteRecursive c 
     INNER JOIN @Table t 
     ON c.Parent = t.Child 
) 

, cteTopAncestorRowNum AS (
    SELECT 
     * 
     ,TopAncestorRowNum = ROW_NUMBER() OVER (PARTITION BY OriginalChild ORDER BY Level DESC) 
    FROM 
     cteRecursive 
) 

SELECT 
    Child = OriginalChild 
    ,TopMostAncestor = Parent 
FROM 
    cteTopAncestorRowNum 
WHERE 
    TopAncestorRowNum = 1