2016-12-02 48 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