再帰的 CTE で生成された最後のレコードを取得するにはどうすればよいでしょうか?

StackOverflow https://stackoverflow.com/questions/35320

質問

以下のコードでは、SQL Server 2005 の再帰 CTE (共通テーブル式) を使用して、基本的な階層構造の最上位の親を見つけようとしています。この階層のルールは、すべての CustID に ParentID があり、CustID に親がない場合は ParentID = CustID となり、それが最上位になります。

DECLARE @LookupID int

--Our test value
SET @LookupID = 1

WITH cteLevelOne (ParentID, CustID) AS
(
        SELECT   a.ParentID, a.CustID
        FROM     tblCustomer AS a
        WHERE    a.CustID = @LookupID
    UNION ALL
        SELECT   a.ParentID, a.CustID
        FROM     tblCustomer AS a
        INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID
        WHERE c.CustID <> a.CustomerID
)

したがって、tblCustomer が次のようになった場合:

ParentID    CustID
5            5
1            8
5            4
4            1

上記のコードから得られる結果は次のとおりです。

ParentID    CustID
4            1
5            4
5            5

私が欲しいのは、その結果の最後の行だけです。

ParentID    CustID
5            5

CTE で生成された最後のレコード (最高レベルの CustID) を返すにはどうすればよいですか?

また、このテーブルには無関係な CustID 階層が複数あるため、単に SELECT * FROM tblCustomer WHERE ParentID = CustID を実行することはできないことにも注意してください。ID 番号は階層内のどこにあるかとは関係がないため、ParentID または CustID で注文することはできません。

役に立ちましたか?

解決

最も高い再帰深度が必要な場合は、次のようなことはできませんか?その後、実際に CTE にクエリを実行するときに、max(Depth) を持つ行を探すだけでよいでしょうか?そのようです:

DECLARE @LookupID int

--Our test value
SET @LookupID = 1;

WITH cteLevelOne (ParentID, CustID, Depth) AS
(
        SELECT   a.ParentID, a.CustID, 1
        FROM     tblCustomer AS a
        WHERE    a.CustID = @LookupID
    UNION ALL
        SELECT   a.ParentID, a.CustID, c.Depth + 1
        FROM     tblCustomer AS a
        INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID 
        WHERE c.CustID <> a.CustID
)
select * from CTELevelone where Depth = (select max(Depth) from CTELevelone)

または、trevor が示唆していることを応用すると、これを同じ CTE で使用できます。

select top 1 * from CTELevelone order by Depth desc

あなたが説明したケースでは、CustomerID が必ずしも注文に使用したかったものではないと思いますが、私も質問について完全に明確ではありませんでした。

他のヒント

問題を完全に理解しているかどうかはわかりませんが、ハック&スラッシュを試すために、次のことを試してみてください。

SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC

これは、GUID のようなものではなく、CustID も例のように適切であることを前提としています。

まず、親の子のいずれかが同じである場合、cte は終了しません。これは再帰的な CTE であるため、終了する必要があります。Parent ID と cust id が同じであると、ループは終了しません。

MSG 530、レベル16、状態1、行15ステートメントが終了しました。ステートメントが完了する前に、最大再帰回数 100 が使い果たされました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top