分层查询使用一些过滤器查找所有 parents

Hierarchical query find all parents with some filters

我的结构如下:

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);

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

我试过类似的方法:

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

但它returns只有"directly"父亲,也就是5.

所以,对于第一个用户,我必须得到它的 parent 红色业务部门:第二个。

为什么我的查询 returns 没有全部 parent?

谢谢

Why my query doesn't returns all the parents?

嗯,它 return 所有 parents
但是没有满足条件CONNECT BY PRIOR B.ID = T.ID_PARENT的parents,所以查询只显示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;

WHen 运行这个查询,在第一步Oracle评估START WITH B.ID = 5条件,并挑选满足这个条件的行,即:

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

下一步oracle对上面的"prior"记录应用CONNECT BY PRIOR B.ID = T.ID_PARENT;条件(从这条记录中取PRIOR ID = 5),然后查找符合条件右边的记录连接结果集中的条件 (5 = ID_PARENT)。
join的结果中没有任何带parent_id = 5的记录,所以connect-by查询的最终结果是:

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