分层查询查找具有一些过滤器的所有父项

时间:2017-04-18 10:53:12

标签: oracle hierarchical

我的结构如下:

CREATE TABLE BUSINESS_UNIT (
  ID NUMBER,
  DESCPRIPTION VARCHAR2(100 CHAR),
  TAG VARCHAR2(10 CHAR)
);
CREATE TABLE USERS (
  ID NUMBER,
  LOGIN VARCHAR2(10 CHAR)
);
CREATE TABLE BU_USERS (
  ID_BU NUMBER,
  ID_USER NUMBER
);
CREATE TABLE BU_TREE (
  ID_BU NUMBER,
  ID_PARENT NUMBER
);

INSERT INTO BUSINESS_UNIT VALUES(1, 'ONE', 'WHITE');
INSERT INTO BUSINESS_UNIT VALUES(2, 'TWO', 'RED');
INSERT INTO BUSINESS_UNIT VALUES(3, 'THREE', 'YELLOW');
INSERT INTO BUSINESS_UNIT VALUES(4, 'FOUR', 'GREEN');
INSERT INTO BUSINESS_UNIT VALUES(5, 'FIVE', 'GREEN');
INSERT INTO BUSINESS_UNIT VALUES(6, 'SIX', 'RED');
INSERT INTO BUSINESS_UNIT VALUES(7, 'SEVEN', 'GREEN');

INSERT INTO USERS VALUES(1, 'USER1');

INSERT INTO BU_USERS VALUES(5, 1);

/*
         ___1w___
     ___2r___    3y___
  __4g       7g       6r
 5g

*/
INSERT INTO BU_TREE VALUES(5, 4);
INSERT INTO BU_TREE VALUES(4, 2);
INSERT INTO BU_TREE VALUES(7, 2);
INSERT INTO BU_TREE VALUES(2, 1);
INSERT INTO BU_TREE VALUES(3, 1);
INSERT INTO BU_TREE VALUES(6, 3);

我必须使用parent获取TAG = "RED"记录。

我尝试过类似的事情:

SELECT
    B.ID
FROM BUSINESS_UNIT B
INNER JOIN BU_TREE T ON (B.ID = T.ID_BU)
START WITH B.ID = (SELECT ID_BU FROM BU_USERS WHERE ID_USER = 1)
CONNECT BY PRIOR B.ID = T.ID_PARENT

但它只返回“直接”父亲,即5。

因此,对于用户来说,我必须得到父红色业务部门:第二名。

为什么我的查询不会返回所有父项?

由于

1 个答案:

答案 0 :(得分:2)

  

为什么我的查询不会返回所有父母?

嗯,确实会让所有父母都
但是没有任何父母符合条件CONNECT BY PRIOR B.ID = T.ID_PARENT,因此查询只显示1条记录。

请查看以下查询,它显示了联接的整个结果集:

SELECT *
FROM BUSINESS_UNIT B
inner JOIN BU_TREE T ON (B.ID = T.ID_BU);

       ID DESCPRIPTI TAG             ID_BU  ID_PARENT
---------- ---------- ---------- ---------- ----------
         2 TWO        RED                 2          1
         3 THREE      YELLOW              3          1
         4 FOUR       GREEN               4          2
         5 FIVE       GREEN               5          4
         6 SIX        RED                 6          3
         7 SEVEN      GREEN               7          2

子查询(SELECT ID_BU FROM BU_USERS WHERE ID_USER = 1)给出5,因此您的查询等同于:

SELECT *
FROM BUSINESS_UNIT B
inner JOIN BU_TREE T ON (B.ID = T.ID_BU);
START WITH B.ID = 5
CONNECT BY PRIOR B.ID = T.ID_PARENT;

运行此查询时,在第一步中,Oracle会评估START WITH B.ID = 5条件,并选择满足此条件的行,即:

       ID DESCPRIPTI TAG             ID_BU  ID_PARENT
---------- ---------- ---------- ---------- ----------
         5 FIVE       GREEN               5          4

在下一步中,oracle将CONNECT BY PRIOR B.ID = T.ID_PARENT;条件应用于上述"之前"记录(从此记录中取PRIOR ID = 5),然后在连接的结果集中搜索满足条件右侧(5 = ID_PARENT)的记录。
在连接结果中没有parent_id = 5的任何记录,因此连接查询的最终结果是:

        ID      ID_BU  ID_PARENT
---------- ---------- ----------
         5          5          4