2012-04-11 55 views
5

使用Oracle 11G(非R2)数据库,我们需要创建报告来显示个人的报告结构属于哪个领导提交。Oracle 11g使用CONNECT BY和多个表创建视图

在高层次上,我们通过在board board_members中查找员工ID来确定董事会中的人员。

board_members表具有可用于访问board_positions的职位ID,并且从那里我们可以确定职位是否在领导委员会中。 (下面的示例)

对于领导委员会中的任何员工,他自己的ID将代表BOARD_LEAD。

对于任何其他员工,report_to值将递归到领导委员会成员被确定并且该人员的ID将为BOARD_LEAD。

我们的顶级员工的report_to等于他们自己的empl_id,而不是更常见的NULL。

为了有希望证明这一点,我在下面设置了样本表,样本数据和样本期望输出。

我想了解如何创建一个将提供这种信息的全职等效和其他报告需求的视图。我确信CONNECT BY将会涉及到,但是我发现Oracle文档很混乱,并且我没有发现任何包含多个表的例子。 (我担心这个缺乏例子有很好的理由。)

是否有可能在Oracle 11g(而不是R2)上编写这样的视图,而不是必须更新每个位置更改的中间表?

Create table board_positions /* If board_position = 'LDRSHPCOMM' this is a top position */ 
(member_id varchar(6),board_position varchar(18)); 

Create table board_members 
(empl_id varchar(6), member_id varchar(6)); 

Create table emp 
(empl_id varchar(6),ename varchar(32),report_to varchar(6)); 

Insert into board_positions values('CEO','LDRSHPCOMM'); 
Insert into board_positions Values('COO','LDRSHPCOMM'); 
Insert into board_positions Values('CFO','LDRSHPCOMM'); 
Insert into board_positions Values('CIO','LDRSHPCOMM'); 
Insert into board_positions values('WANABE','NEWBIE'); 

Insert into emp ('TOPDOG','Big Guy','TOPDOG'); 
Insert into emp ('WALLET','Money Bags','TOPDOG'); 
Insert into emp ('OPSGUY','Meikut Work','TOPDOG'); 
Insert into emp ('INFGUY','Comp U Turk','TOPDOG'); 
Insert into emp ('HITECH','Number 2','INFGUY'); 
Insert into emp ('LOTECH','Number 3','HITECH'); 
Insert into emp ('PROGMR','Nameless Blameless','LOTECH'); 
insert into emp ('FLUNKY','Ida Dunnit','PROGMR'); 

Insert into board_members ('TOPDOG','CEO'); 
Insert into board_members ('WALLET','CFO'); 
Insert into board_members ('OPSGUY','COO'); 
Insert into board_members ('INFGUY','CIO'); 
Insert into board_members ('HITECH','WANABE'); /* Board position not on the leadership committee */ 

使用类似:

CREATE VIEW LEADER_VIEW AS 
    WITH T1 AS (SELECT e.empl_id, (something) as board_lead 
       , (something) as board_lead_pos 
      FROM emp e 
      LEFT OUTER JOIN board_members bm 
         ON bm.empl_id = e.empl_id 
      LEFT OUTER JOIN board_positions bp 
         on bp.member_id = bm.member_id 
      ... 
      CONNECT BY PRIOR empl_id = report_to 
      START WITH empl_id = report_to 
      ) 
    SELECT * FROM T1 

(但我知道还有很多更给它莫过于此!)

所需的输出例子。 。 。

TOPDOG   TOPDOG CEO (Because self is on LDRSHPCOMM) 
WALLET   WALLET CFO (Because self is on LDRSHPCOMM) 
OPSGUY   OPSGUY COO (Because self is on LDRSHPCOMM) 
INFGUY   INFGUY CIO (Because self is on LDRSHPCOMM) 
HITECH   INFGUY CIO (Because REPORTTO is on LDRSHPCOMM) 
LOTECH   INFGUY CIO (Because REPORTTO->REPORTTO is on LDRSHPCOMM) 
PROGMR   INFGUY CIO (REPORTTO->REPORTTO->REPORTTO is on LDRSHPCOMM) 
FLUNKY   INFGUY CIO (You know by now.) 

回答

5

你可以做这样的事情:

SQL> SELECT * 
    2 FROM (SELECT empl_id, ename, report_to, 
    3     member_id, board_position, 
    4     MAX(lvl) over(PARTITION BY empl_id) maxlvl, lvl 
    5    FROM (SELECT connect_by_root(e.empl_id) empl_id, 
    6       connect_by_root(e.ename) ename, 
    7       bm.empl_id report_to, 
    8       LEVEL lvl, bp.* 
    9      FROM emp e 
10      LEFT JOIN board_members bm 
11        ON e.empl_id = bm.empl_id 
12      LEFT JOIN board_positions bp 
13        ON bm.member_id = bp.member_id 
14     CONNECT BY NOCYCLE e.empl_id = PRIOR e.report_to 
15       AND (PRIOR bp.board_position IS NULL 
16        OR PRIOR bp.board_position != 'LDRSHPCOMM'))) 
17 WHERE lvl = maxlvl; 

EMPL_ID ENAME       REPORT_TO MEMBER_ID BOARD_POSITION  
------- -------------------------------- --------- --------- ------------------ 
FLUNKY Ida Dunnit      INFGUY CIO  LDRSHPCOMM   
HITECH Number 2       INFGUY CIO  LDRSHPCOMM   
INFGUY Comp U Turk      INFGUY CIO  LDRSHPCOMM   
LOTECH Number 3       INFGUY CIO  LDRSHPCOMM   
OPSGUY Meikut Work      OPSGUY COO  LDRSHPCOMM   
PROGMR Nameless Blameless    INFGUY CIO  LDRSHPCOMM   
TOPDOG Big Guy       TOPDOG CEO  LDRSHPCOMM   
WALLET Money Bags      WALLET CFO  LDRSHPCOMM  

我有没有条款启动,因为我要开始为所有员工的分层查询。对于每位员工,我都会浏览分层数据,直到找到一名经理担任领导委员会(CONNECT BY条款)的董事会成员。

外部查询过滤相关行。