2016-12-02 8 views
0

は、のは、それは次のようになりましょう:currentためトラブル私はテーブルを持っている

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

cスタンドと2 Iのc値が与えられparent

ためpスタンド親を持たない最上位の祖先を返します。この値は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つの結合で行うことができ、後者は再帰的なcteのような手法をとるためです。また、トップの親は常に実際にテーブルのレコードを持っていますか? – 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 
関連する問題