2012-04-11 71 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條款)的董事會成員。

外部查詢過濾相關行。