1

次の表を検討してください

+--------+-------+--+
| Parent | Child |  |
+--------+-------+--+
|      1 |     2 |  |
|     10 |    13 |  |
|      2 |     3 |  |
|      3 |     4 |  |
|     13 |    14 |  |
|      4 |     5 |  |
|     15 |    16 |  |
|      5 |     1 |  |
+--------+-------+--+

この表では、親子の階層に従っています。この表から、次の表の結果が必要です

+--------+-------+--+
| Parent | Child |  |
+--------+-------+--+
|      1 |     2 |  |
|      2 |     3 |  |
|      3 |     4 |  |
|      4 |     5 |  |
|      5 |     1 |  |
+--------+-------+--+

コードで階層を取得したい(1-2-3-4-5-1)。現在、親を取得した後に各子を照会しています (場合によっては、子は 5-1 のような以前の親のいずれかになります)。長い階層の場合、多数のクエリが実行されます。これをより効率的にするにはどうすればよいですか?

4

3 に答える 3

4
;with cte(parent,child) as (
    select parent, child
      from sometable
     where parent = 1  --- seed
     UNION ALL
    select t.parent, t.child
      from sometable t
      join cte on cte.child = t.parent
)
    select *
      from cte;

無限ループを回避するには、通過した ID のリストを保存する必要があります。

;with cte(parent,child,traversed) as (
    select parent, child, ',' + right(parent,10) + ','
      from sometable
     where parent = 1  --- seed
     UNION ALL
    select t.parent, t.child, cte.traversed + right(t.parent,10) + ','
      from sometable t
      join cte on cte.child = t.parent
     where not cte.traversed like ',%' + t.parent + '%,'
)
    select parent, child
      from cte;

ただし、LIKE チェックを実行する必要があるため、それほど高速には実行されません。

于 2013-04-24T10:47:12.293 に答える