2008-08-29 12 views
1

以下のコードでは、SQL Server 2005で再帰的なCTE(共通テーブル式)を使用して、基本的な階層構造の最上位の親を検索しています。この階層のルールでは、すべてのCustIDにParentIDがあり、CustIDに親がない場合はParentID = CustIDであり、最も高いレベルです。再帰CTEで最終レコードをどのように生成しますか?

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 

どのようにd o CTEで生成された最後のレコードを返します(最高レベルのCustIDになります)。

また、このテーブルには無関係な複数のCustID階層が存在するため、SELECT * FROM tblCustomer WHERE ParentID = CustIDだけではできません。 ID番号が階層内のどこに関連していないので、ParentIDまたはCustIDで注文することはできません。

答えて

2

最高の再帰深度が必要な場合は、このようなことはできませんか?次に、実際に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) 

や、トレバーは示唆して何適応、これは同じCTEで使用することができます:これと同様

select top 1 * from CTELevelone order by Depth desc 

私は、得意先は、あなたがケースにすることによって注文したい必ずしもたものだったとは思いませんあなたは説明しましたが、私はその質問についても完全にはっきりしていませんでした。

1

私は問題を完全に理解してかどうか分からないが、ちょうどあなたが試みることができることで&スラッシュをハックする:

SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC 

お客様IDは、例のように順番でもあり、そしてないことを前提としていGUIDのようなもの。

0

最初に、親の子が同じであれば、cteは終了しません。それは再帰的なCTEであるため、終了させる必要があります。 ParentとCust IDが同じであれば、ループは終了しません。

メッセージレベル530、レベル16、状態1、行15 ステートメントが終了しました。文の完了前に最大再帰100が使い尽くされました。

関連する問題