2012-04-11 20 views
5

Utilizzando il database Oracle 11G (non R2), è necessario creare report che mostrino a quale Comitato di gestione appartiene la struttura di reporting di una persona.Oracle 11g CREATE VIEW utilizzando CONNECT BY e più tabelle

Ad un livello elevato, determiniamo la presenza di un individuo sul tabellone individuando l'ID dipendente in table_members.

La tabella board_members ha un ID di posizione che può essere utilizzato per accedere a board_positions e da lì è possibile determinare se la posizione è nel comitato di leadership. (Esempi di seguito)

Per qualsiasi dipendente che si trova nel comitato di leadership, il proprio ID rappresenterà BOARD_LEAD.

Per qualsiasi altro dipendente, il valore report_to viene ripetuto fino a quando non viene identificato un membro del comitato di direzione e l'ID di tale persona sarà BOARD_LEAD.

Il nostro personale di livello superiore ha report_to uguale al proprio empl_id, piuttosto che al più comune NULL.

Per dimostrarlo, ho impostato tabelle di esempio, dati di esempio e l'output desiderato di seguito.

Sto cercando di capire come creare una VISTA che fornisca tali informazioni per l'equivalenza a tempo pieno e altre esigenze di segnalazione. Sono convinto che sarà coinvolto CONNECT BY, ma trovo la documentazione di Oracle confusa e non ho trovato esempi che includano più tabelle come questa. (Temo che ci sia una buona ragione per questa mancanza di esempio.)

E 'possibile scrivere tale vista su Oracle 11g (non R2) piuttosto che su una tabella intermedia che deve essere aggiornata con ogni cambio di posizione?

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

Usando qualcosa di simile:

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 

(Ma so che c'è molto di più ad esso che questo!)

esempio output desiderato. . .

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

risposta

5

Si potrebbe fare qualcosa di simile:

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  

Non ho AVVIO CON clausola perché voglio iniziare la query gerarchica per tutti i dipendenti. Per ciascun dipendente passo attraverso i dati gerarchici finché non trovo un manager che è un membro del consiglio di amministrazione del comitato di leadership (clausola CONNECT BY).

Le query esterne filtrano le righe pertinenti.