0

私はT-SQLのCTEに不慣れですが、それらを愛しています。ただし、作成しているこの特定のストアドプロシージャのロジックを正しく取得できません。

Table A列で与えられる:

Id Name Inherits ...

列Inheritsは、この同じテーブルの別の行へのIDであるintを格納します。

そしてTable B列で:

Id Name AId ...

ここで、AIdは表Aの行への外部キーです。

CTEを使用して、の任意の行(x)から開始し、のAすべての行を収集してから、xを。BAId = x.Id指す行に設定することにより、Aで上向きに再帰する方法を教えてx.Inheritsください。これはまで続行する必要がありますx.Inherits IS NULL

したがって、全体的な効果は、開始A Idの関連するB行を返し、次にAのInherits列を再帰的に調べることによって検出したすべての継承されたB行を返したいということです。

私の考えは、任意の行からAの「ルート」に再帰するようにCTEを設定することです。各再帰呼び出しの内部には、BへのJOINがあります。これは私が得た限りです。

WITH c 
AS
(

    SELECT A.Inherits,A.Id, B.Name, 1 AS Depth
    FROM tbl_A A
    INNER JOIN tbl_B B ON B.AId = A.Id
    WHERE A.Id = @ArbitraryStartingAId

    UNION ALL

    SELECT T.Inherits,T.Id, c.Name, c.Depth + 1 AS 'Level'
    FROM tbl_A T        
    INNER JOIN c ON T.Id = c.Inherits

)
SELECT *
FROM c 

生成するもの:

1        4  b_val   1
11       1  b_val   2
NULL    11  b_val   3

どこb_valからTable B row (y)どこへ@ArbitraryStartingAId = y.AId。Aの再帰は機能していますが、反復ごとに対応する正しいBデータを取得していません。

誰かがこれを書き直して私が必要とする結果を生み出すのを手伝ってくれるなら、それは素晴らしいことです。

どうもありがとう

4

2 に答える 2

2

私たちが持っていると仮定します

CREATE TABLE A ( Id int, Name nvarchar(10), Inherits int );
CREATE TABLE B ( Id int, Name nvarchar(10), AId int );

そしていくつかのデータ:

INSERT A VALUES ( 1, 'one', 2 );
INSERT A VALUES ( 2, 'two', 3 );
INSERT A VALUES ( 3, 'three', null );
INSERT A VALUES ( 4, 'four', 3 );

INSERT B VALUES ( 1, 'B one', 1 );
INSERT B VALUES ( 2, 'B two', 2 );
INSERT B VALUES ( 3, 'B three', 3 );
INSERT B VALUES ( 4, 'B four', 4 );

にCTEを構築してAから、参加できBます。

WITH cteA AS 
(
    -- Anchor
    SELECT Id, Name, Inherits FROM A
    WHERE Id = 1
    UNION 
    -- Recursive
    SELECT A.Id, A.Name, A.Inherits FROM A
    INNER JOIN cteA ON A.Id = cteA.Inherits
)
SELECT * FROM cteA INNER JOIN B ON cteA.Id = B.AId;

取得するには(アンカーを1):

Id          Name       Inherits    Id          Name       AId
----------- ---------- ----------- ----------- ---------- -----------
1           one        2           1           B one      1
2           two        3           2           B two      2
3           three      NULL        3           B three    3
于 2012-12-04T15:29:07.283 に答える
0

これが私が今いるところです。正しいデータが返されるので、それは1つの可能な答えです。

WITH c 
AS
(
    SELECT A.Inherits,A.Id, B.Name, 1 AS Depth
    FROM tbl_A A
    INNER JOIN tbl_B B ON B.AId = A.Id
    WHERE A.Id =@ArbitraryStartingAId

    UNION ALL

    SELECT T.Inherits,T.Id, T.Name, B.Name, c.Depth + 1 AS 'Level'
    FROM tbl_A T
    INNER JOIN tbl_B B ON B.AId = T.Id      
    INNER JOIN c ON T.Id = c.Inherits
)
SELECT DISTINCT *
FROM c ORDER BY Depth ASC

ルートレベルBの行を2回返すため、少し汚れた感じがします。したがって、DISTINCT演算子はこれらを除外します... ??

于 2012-11-29T15:52:42.453 に答える