1

私はオラクルの初心者です...比較的言えば...

継承した Oracle テーブルで CTE を使用しようとしています。「トップレベル」が明確に定義されていないという点で、私が望んでいたよりも少し複雑です。

create table testConnectBy ( parent number, child number );

insert into testConnectBy values ( 1,  1);
insert into testConnectBy values ( 1, 11);
insert into testConnectBy values ( 1, 12);
insert into testConnectBy values ( 2,  2);
insert into testConnectBy values ( 2, 13);
insert into testConnectBy values (11, 11);
insert into testConnectBy values (11, 20);
insert into testConnectBy values (11, 21);
insert into testConnectBy values (12, 12);
insert into testConnectBy values (12, 22);
insert into testConnectBy values (12, 23);
insert into testConnectBy values (12, 24);
insert into testConnectBy values (13, 13);
insert into testConnectBy values (13, 30);
insert into testConnectBy values (13, 31);
insert into testConnectBy values (30, 30);
insert into testConnectBy values (30, 40);

このクエリは、必要なすべての行を取得しますが、いくつかの重複があります (これは、問題の最初の部分であり、どのように削除するのが最善かということです)。ループの問題 (親 == 子) があるため、nocycle を含める必要がありました。

select *
  from testConnectBy 
  start with parent = '1'
  connect by nocycle prior child = parent;

次の問題は、たとえば 11 を入力して、すべての親と子を見つけられるようにしたいということです。どの親子が11に関係しているかはわかりません。ただ、11を使って見つける必要があります。

このクエリは 11 の子のみを返します。両方の「方向」を返す方法はありますか?

select *
  from testConnectBy 
  start with parent = '11'
  connect by nocycle prior child = parent;

前もって感謝します。

4

1 に答える 1

1

最初の質問については、以下を使用してください。PATHでチェックできる重複はありません

SELECT
            PARENT,
            CHILD,
            LEVEL,
            CONNECT_BY_ISLEAF AS ISLEAF,
            CONNECT_BY_ISCYCLE AS ISCYCLE,
            CONNECT_BY_ROOT PARENT
            || SYS_CONNECT_BY_PATH ( CHILD,
                                ' ~ ' )
                AS PATH
       FROM
            TESTCONNECTBY
       CONNECT BY
            NOCYCLE PARENT = PRIOR CHILD
       START WITH
            PARENT = '1';

これは戻ります

1    1    1    0    1    1 ~ 1
1    11    2    0    1    1 ~ 1 ~ 11
11    20    3    1    0    1 ~ 1 ~ 11 ~ 20
11    21    3    1    0    1 ~ 1 ~ 11 ~ 21
1    12    2    0    1    1 ~ 1 ~ 12
12    22    3    1    0    1 ~ 1 ~ 12 ~ 22
12    23    3    1    0    1 ~ 1 ~ 12 ~ 23
12    24    3    1    0    1 ~ 1 ~ 12 ~ 24
1    11    1    0    1    1 ~ 11
11    20    2    1    0    1 ~ 11 ~ 20
11    21    2    1    0    1 ~ 11 ~ 21
1    12    1    0    1    1 ~ 12
12    22    2    1    0    1 ~ 12 ~ 22
12    23    2    1    0    1 ~ 12 ~ 23
12    24    2    1    0    1 ~ 12 ~ 24

PARENT=CHILDREN を避けたい場合は、

SELECT
            PARENT,
            CHILD,
            LEVEL,
            CONNECT_BY_ISLEAF AS ISLEAF,
            CONNECT_BY_ISCYCLE AS ISCYCLE,
            CONNECT_BY_ROOT PARENT
            || SYS_CONNECT_BY_PATH ( CHILD,
                                ' ~ ' )
                AS PATH
       FROM
            (SELECT * FROM TESTCONNECTBY WHERE PARENT <> CHILD)
       CONNECT BY
            NOCYCLE PARENT = PRIOR CHILD
       START WITH
            PARENT = '1';

結果は

1    11    1    0    0    1 ~ 11
11    20    2    1    0    1 ~ 11 ~ 20
11    21    2    1    0    1 ~ 11 ~ 21
1    12    1    0    0    1 ~ 12
12    22    2    1    0    1 ~ 12 ~ 22
12    23    2    1    0    1 ~ 12 ~ 23
12    24    2    1    0    1 ~ 12 ~ 24

2 番目の質問については、以下のスニペットを使用できます

SELECT
      *
FROM
      (SELECT
            PARENT,
            CHILD,
            LEVEL,
            CONNECT_BY_ISLEAF AS ISLEAF,
            CONNECT_BY_ISCYCLE AS ISCYCLE,
            CONNECT_BY_ROOT PARENT
            || SYS_CONNECT_BY_PATH ( CHILD,
                                ' ~ ' )
                AS PATH
       FROM
            TESTCONNECTBY
       CONNECT BY
            NOCYCLE PARENT = PRIOR CHILD
       START WITH
            PARENT = '1')
WHERE
      PARENT = 11
      OR CHILD = 11;

このクエリは

1    11    2    0    1    1 ~ 1 ~ 11
11    20    3    1    0    1 ~ 1 ~ 11 ~ 20
11    21    3    1    0    1 ~ 1 ~ 11 ~ 21
1    11    1    0    1    1 ~ 11
11    20    2    1    0    1 ~ 11 ~ 20
11    21    2    1    0    1 ~ 11 ~ 21

親 11 には子 11 があるため、自分自身の子を除外したい場合は、

SELECT
      *
FROM
      (SELECT
            PARENT,
            CHILD,
            LEVEL,
            CONNECT_BY_ISLEAF AS ISLEAF,
            CONNECT_BY_ISCYCLE AS ISCYCLE,
            CONNECT_BY_ROOT PARENT
            || SYS_CONNECT_BY_PATH ( CHILD,
                                ' ~ ' )
                AS PATH
       FROM
            (SELECT * FROM TESTCONNECTBY WHERE PARENT <> CHILD)
       CONNECT BY
            NOCYCLE PARENT = PRIOR CHILD
       START WITH
            PARENT = '1')
WHERE
      PARENT = 11
      OR CHILD = 11;

どちらが返されますか

1    11    1    0    0    1 ~ 11
11    20    2    1    0    1 ~ 11 ~ 20
11    21    2    1    0    1 ~ 11 ~ 21  
于 2013-10-16T10:27:05.100 に答える