5

質問

再帰的な CTE クエリがありますが、ループが作成されると失敗します。単純なループ (例: 1 -> 2 -> 1) は既に修正しましたが、より複雑なループ (例: 1 -> 2 -> 3 -> 2) は修正できません。

クエリの詳細

テスト テーブルには、Base と Parent の 2 つの列があります。すべての祖先のリストが必要です。

私のクエリは、test2 から開始すると以下のサンプル データに対して機能しますが、test1 から開始すると機能しません。

サンプルデータ

Base    Parent
----    ------
test1   test2
test2   test3
test3   test2

SQL クエリ (試行した修正はコメントでマークされています)

;with sample_data (Base, Parent) as (
    select 'test1', 'test2'
    union select 'test2', 'test3'
    union select 'test3', 'test2'
),
nt_list (Base, Ancestor, [level]) as (
        select  Base,
                Parent Ancestor,
                1 [level]
        from    sample_data
        where   Base = 'test1' -- START HERE
        union all
        select  ntl.Base,
                nt.Parent,
                ntl.[level] + 1 [level]
        from    nt_list ntl
        join    sample_data nt on ntl.Ancestor = nt.Base
        where   nt.Parent <> ntl.Base -- fix recursive bug (e.g. 1 -> 2 -> 1)
        -- WHAT I TRIED TO ADD BUT CANNOT: (e.g. 1 -> 2 -> 3 -> 2)
        and     nt.Parent in (select Ancestor from nt_list)
)
select  distinct
        ntl.Base,
        ntl.Ancestor
from    nt_list ntl
order by Ancestor

SQL エラー: 共通テーブル式 'nt_list' の再帰メンバーに複数の再帰参照があります。

4

4 に答える 4

3

最終版。仮定'/'は、ベース名または親名の一部になることはありません。

;with sample_data (Base, Parent) as (
    -- TEST 1
    --        select 'test1', 'test2'
    --union   select 'test2', 'test3'
    --union   select 'test3', 'test2'
    -- TEST 2
            select 'test1', 'test2'
    union   select 'test2', 'test3'
    union   select 'test3', 'test4'
    union   select 'test3', 'test9'
    union   select 'test4', 'test5'
    union   select 'test5', 'test3'
    union   select 'test9', 'test8'
    -- TEST 3
    --        select 'test1', 'test2'
    --union   select 'test2', 'test3'
    --union   select 'test3', 'test1'
    -- TEST 4
    --        select  'test1', 'test1'
    --union   select  'test1', 'test2'
),
nt_list (Base, Ancestor, [level], [path]) as (
        select  Base,
                Parent Ancestor,
                1 [level],
                '/' + convert(varchar(max), rtrim(Base)) + '/' [path]
        from    sample_data
        where   Base = 'test1' -- START HERE
        union all
        select  ntl.Base,
                nt.Parent,
                ntl.[level] + 1 [level],
                ntl.[path] + rtrim(nt.Base) + '/'
        from    nt_list ntl
        join    sample_data nt on ntl.Ancestor = nt.Base
        where   ntl.path not like '%/' + rtrim(nt.Parent) + '/%'
)
select  distinct
        ntl.Base,
        ntl.Ancestor
from    nt_list ntl
order by Ancestor
于 2013-02-19T07:40:05.537 に答える
0

私の現在の回避策は、レベル制限を追加and ntl.[level] <= 100して(クエリに追加して)select distinct、重複したエントリを削除することです。

于 2013-02-18T09:30:50.543 に答える
0

このケースは完璧ですが、次のような他のアイテムと同様に:

    select 'test1', 'test2'
         union select 'test2', 'test3'
         union select 'test3', 'test4'
         union select 'test4', 'test5'
         union select 'test10', 'test11'
         union select 'test11', 'test30'
         ...

結果は次のようになります。

    test1   test1 <- adding this
    test1   test2
    test1   test3
    test1   test4
    test1   test5
    test10  test10 <- adding this to multiple bases
    test10  test11
    test10  test30
于 2013-06-26T00:52:47.720 に答える