3

テーブル名ツリーがあり、1 つはp、2 番目はchの 2つの列があります。

p       ch 
-------------
1       2                   
1       3 
1       4 
2       5 
2       6 
7       8 
9       10 
11      12 
6       13 
13      14 
14      15 
14      16

私が望む出力は、親にリンクされたすべての子です。たとえば、すべての親要素と子要素を見つける必要がある入力として「1」を指定すると、この場合、1 は 2,3,4 の親であり、2 は 5 の親です...この場合、私は以下に示すように、リンクされたすべての子要素と親自体が必要です。

ParentChilds
------------
1
2
3
4
5
6
13
14
15
16

以下は私が書いたクエリです。テーブルに大きなデータがあるため、それが最善の解決策であるか、より良い方法で実行できるかを確認したいと思います。

with LinkedAccounts (p, ch, orig_recur, dest_recur, lvl) as (
            select n.p
    , n.ch
    , 1 orig_recur
     , case n.p
           when 1 then ch
                   else p
        end dest_recur
     , 1 lvl
   from tree n
 where n.p = 1
   or n.ch = 1 union all
select n.p
     , n.ch
    , LinkedAccounts.dest_recur orig_recur
     , case n.p
         when LinkedAccounts.dest_recur then n.ch
                           else n.p
       end dest_recur
     , LinkedAccounts.lvl + 1 lvl
  from LinkedAccounts
  join tree n
        on (n.p = LinkedAccounts.dest_recur and n.ch != LinkedAccounts.orig_recur)
        or (n.ch = LinkedAccounts.dest_recur and n.p != LinkedAccounts.orig_recur)
)
 search breadth first by orig_recur, dest_recur set ordering
cycle ch,
 p set is_cycle to '1' default '0'   select distinct p    from LinkedAccounts    union     Select Distinct ch    from LinkedAccounts;
4

2 に答える 2

1

このアプローチは、ルートから始めて各親をその子に結合するという、より伝統的な再帰的な cte アプローチを使用するため、少し読みやすいかもしれません。ルート ノードは、それ自体が親を持たないノードとして識別されます ( where not exists)。

with LinkedAccounts(topRoot, parent, child, lvl)
as 
    (
        select r.p as topRoot, r.p as parent, r.ch as child, 1 as lvl
            from tree r
            where not exists
            (
                select 1 from tree t where r.p = t.ch
            )

        union all

        select la.topRoot
            , ch.p
            , ch.ch
            , la.lvl + 1
        from LinkedAccounts la
            inner join tree ch
            on ch.p = la.child
    ),
    ParentAndChild as
    (
        select topRoot, parent as node, lvl from LinkedAccounts

        union all

        select topRoot, child as node, lvl from LinkedAccounts
    )
    select distinct node
        from ParentAndChild
        where topRoot = 1
        order by node ASC;

ここでSqlFiddle

余談ですが、階層内の命名規則は珍しいものです -ch通常はnodeid(しかしparent親/親 ID になります) - これは、ノードに追加の列を許可するノードをモデル化します。一見、ノードではなく、接続関係そのものをモデリングしているように見えますか?

于 2015-06-23T05:28:02.847 に答える