2012-09-10 10 views
6

Con questo ho una gran voglia. Sto cercando di scrivere una query (usando Oracle), su una tabella con una relazione ricorsiva (gerarchica) e ottenere il numero totale di record memorizzati in un'altra tabella a e sotto ciascun nodo nella struttura. L'altra tabella ha solo record associati ai nodi foglia. Tuttavia, voglio ottenere i totali a e sotto ogni nodo nell'albero. Ad esempio, supponiamo di avere due tabelle. DIRS contiene i nomi di directory e una relazione ricorsiva che identifica la struttura delle directory e file contiene informazioni sui file con una chiave esterna per DIRS indicare la directory del file risiede in:Ottenimento di conteggi/totali per ogni livello di una query gerarchica tramite CONNECT BY

DIRS 
==== 
DIR_ID 
PARENT_DIR_ID 
DIR_NAME 

FILES 
===== 
FILE_ID 
FILE_NAME 
DIR_ID 
FILE_SIZE 

Se DIRS contiene:

DIR_ID PARENT_DIR_ID DIR_NAME 
====== ============= ======== 
1      ROOT 
2  1    DIR1_1 
3  1    DIR1_2 
4  2    DIR2_1 
5  2    DIR2_2 

e file contiene

FILE_ID FILE_NAME DIR_ID FILE_SIZE 
======= ========= ====== ========= 
1   test1.txt 5  100 
2   test2.txt 5  200 
3   test5.txt 5   50 
4   test3.txt 3  300 
5   test4.txt 3  300 
6   test6.txt 4  100 

voglio una query che restituisce il percorso insieme al numero di file in o al di sotto di ogni nodo del hier archia. Fondamentalmente un rollup del numero di file. Così il risultato della query sarebbe simile:

Path     File_Count 
=====     =========== 
/ROOT     6 
/ROOT/DIR1_1   4 
/ROOT/DIR1_1/DIR2_1  1 
/ROOT/DIR1_1/DIR2_2  3 
/ROOT/DIR1_2   2 

UPDATE sceneggiatura SQL per creare le tabelle con i dati di esempio per corrispondere quanto sopra:

create table DIRS (dir_id number(38) primary key 
    , parent_dir_id number(38) null references DIRS(dir_id) 
    , dir_name varchar2(128) not null); 

create table FILES (file_id number(38) primary key 
    , file_name varchar2(128) not null 
    , dir_id number(38) not null references DIRS(dir_id) 
    , file_size number not null 
    , unique (dir_id, file_name)); 

insert into DIRS 
select 1, null, 'ROOT' from dual 
union all select 2, 1, 'DIR1_1' from dual 
union all select 3, 1, 'DIR1_2' from dual 
union all select 4, 2, 'DIR2_1' from dual 
union all select 5, 2, 'DIR2_2' from dual; 

insert into files 
select 1, 'test1.txt', 5, 100 from dual 
union all select 2, 'test2.txt', 5, 200 from dual 
union all select 3, 'test5.txt', 5, 50 from dual 
union all select 4, 'test3.txt', 3, 300 from dual 
union all select 5, 'test4.txt', 3, 300 from dual 
union all select 6, 'test6.txt', 4, 100 from dual; 

commit; 
+0

Quale versione di Oracle? 11g R2 aggiunge il factoring sub-query ricorsivo che potrebbe offrire una soluzione più chiara di 'connect by'. –

+0

Sì 11g R2. Esaminerà "sub-query factoring". Non mi è familiare. – GregH

+0

Sembra che sia stato aggiunto il factoring di sub-query in Oracle 9.2 – GregH

risposta

1
select sys_connect_by_path(D.dir_name, '/'), S.count_distinct_file_id 
from DIRS D 
inner join (select subtree_root_dir_id 
      , count(distinct file_id) count_distinct_file_id 
     from (select distinct connect_by_root D.DIR_ID subtree_root_dir_id 
        , F.file_id 
       from DIRS D 
       left outer join FILES F on F.dir_id = D.dir_id 
       start with 1=1 connect by prior D.dir_id = D.parent_dir_id) 
     group by subtree_root_dir_id) S 
    on D.dir_id = S.subtree_root_dir_id 
start with D.dir_id = 1 connect by prior D.dir_id = D.parent_dir_id 

dà i risultati che hai chiesto, ma il mio istinto dice che non vedo nulla, e che la domanda può essere molto più semplice. (Si prega di non accettare questa risposta fino a pochi giorni sono passati, nella speranza che qualcuno invia una risposta migliore.)

4

Questo è abbastanza semplice:

09:38:54 [email protected]_xe> l          
    1 select sys_connect_by_path(dp.dir_name, '/') path  
    2   ,(select count(file_id)      
    3    from dirs dc        
    4     ,files f        
    5   where f.dir_id(+) = dc.dir_id    
    6   connect by prior dc.dir_id = dc.parent_dir_id 
    7   start with dc.dir_id = dp.dir_id   
    8   ) count          
    9 from dirs dp          
10 connect by prior dp.dir_id = dp.parent_dir_id  
11* start with dp.parent_dir_id is null     
09:38:55 [email protected]_xe>/          

PATH        COUNT     
------------------------------ ----------     
/ROOT         6     
/ROOT/DIR1_1       4     
/ROOT/DIR1_1/DIR2_1      1     
/ROOT/DIR1_1/DIR2_2      3     
/ROOT/DIR1_2       2     

5 rows selected.           

Elapsed: 00:00:00.02          
Problemi correlati