2012-04-11 11 views
5

Mit Oracle 11G (nicht R2) -Datenbank müssen wir Berichte erstellen, die zeigen, zu welchem ​​Leadership Committe die Berichtsstruktur eines einzelnen gehört.Oracle 11g CREATE VIEW mit CONNECT BY und mehreren Tabellen

Auf einer hohen Ebene bestimmen wir die Anwesenheit einer Person auf der Platine, indem Sie die Mitarbeiter-ID in der Tabelle board_members suchen.

Die Tabelle board_members hat eine Positions-ID, die für den Zugriff auf board_positions verwendet werden kann, und von dort aus können wir bestimmen, ob die Position im Führungskomitee ist. (Beispiele unten.)

Für jeden Mitarbeiter, der Mitglied des Führungsausschusses ist, steht seine eigene ID für BOARD_LEAD.

Für jeden anderen Mitarbeiter wird der Wert report_to wiederholt, bis ein Mitglied des Leadership Committee identifiziert wird und die ID dieser Person BOARD_LEAD lautet.

Unsere Top-Level-Mitarbeiter haben report_to ihre eigene empl_id, anstatt der üblicheren NULL.

Um dies hoffentlich zu demonstrieren, habe ich Beispieltabellen, Beispieldaten und Probe gewünschte Ausgabe unten eingerichtet.

Ich versuche zu verstehen, wie Sie eine VIEW erstellen, die solche Informationen für Vollzeitäquivalenz und andere Berichtsanforderungen zur Verfügung stellt. Ich bin überzeugt, dass CONNECT BY involviert sein wird, aber ich finde die Oracle-Dokumentation verwirrend und ich habe keine Beispiele gefunden, die mehrere Tabellen wie diese enthalten. (Ich fürchte, es gibt einen guten Grund für diesen Mangel an Beispiel.)

Ist es überhaupt möglich, eine solche Ansicht bei Oracle 11g (nicht R2) zu schreiben, anstatt eine Zwischentabelle, die bei jeder Positionsänderung aktualisiert werden muss?

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 */ 

mit so etwas wie:

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 

(Aber ich weiß, dass es viel mehr dahinter als das!)

Wunschausgabebeispiel. . .

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

Antwort

5

Man könnte so etwas tun:

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  

Ich habe keine START WITH-Klausel, weil ich die hierarchische Abfrage für alle Mitarbeiter starten wollen. Für jeden Mitarbeiter durchlaufe ich die hierarchischen Daten, bis ich einen Manager finde, der Mitglied des Leitungsausschusses ist (CONNECT BY-Klausel).

Die äußeren Abfragen filtern die relevanten Zeilen.