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

对于第二个问题,您可以使用以下代码段

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 回答