使用CONNECT BY和多个表的Oracle 11g CREATE VIEW

时间:2012-04-11 01:45:52

标签: sql oracle view oracle11g hierarchical-data

使用Oracle 11G(非R2)数据库,我们需要创建报告,以显示个人报告结构所属的领导委员会。

在较高级别,我们通过在表board_members中找到员工ID来确定个人在董事会中的存在。

board_members表有一个位置ID,可用于访问board_positions,从那里我们可以确定该职位是否在领导委员会。 (以下样本。)

对于担任领导委员会的任何员工,他自己的身份证将代表BOARD_LEAD。

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

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

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

我正在尝试了解如何创建一个VIEW,以便为完整时间等效和其他报告需求提供此类信息。我确信将涉及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.)

1 个答案:

答案 0 :(得分:6)

你可以这样做:

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      

我没有START WITH子句,因为我想为所有员工启动分层查询。对于每个员工,我都会浏览分层数据,直到找到一名经理作为领导委员会的董事会成员(CONNECT BY子句)。

外部查询过滤相关行。