简体   繁体   中英

Oracle hierarchical sql with rollup count

How would I write SQL in Oracle to return tree view with rolloup count:

SQL would return this:

KLAS - COUNT

----------------------------------------------

ROOT - 10

   KLAS1 - 5

       KLAS2 - 2

       KLAS3 - 3

  KLAS4 - 5

       KLAS5 - 5

  KLAS6 - 0

       KLAS7 - 0

I have two tables, one is where is structure hold, second is where I have data. Both tables are joined by klas coumn

Code for reproducing tables:

create table table1 (id number, parent_id number, klas varchar2(10));  
insert into table1 (id, parent_id, klas) values (1, null, 'ROOT');  
insert into table1 (id, parent_id, klas) values (2, 1, 'KLAS1');  
insert into table1 (id, parent_id, klas) values (3, 2, 'KLAS2');  
insert into table1 (id, parent_id, klas) values (4, 2, 'KLAS3');  
insert into table1 (id, parent_id, klas) values (5, 1, 'KLAS4');  
insert into table1 (id, parent_id, klas) values (6, 5, 'KLAS5');  
insert into table1 (id, parent_id, klas) values (7, 1, 'KLAS6');  
insert into table1 (id, parent_id, klas) values (8, 7, 'KLAS7');  



create table table2 (klas varchar2(10), cnt number);  
insert into table2(klas, cnt) values ('KLAS2', 2);  
insert into table2(klas, cnt) values ('KLAS3', 3);  
insert into table2(klas, cnt) values ('KLAS5', 5);  

commit;  

Regards, Igor

with c1 (parent_id, id, klas, p, o) as
(
  select 
     parent_id, id, klas, '' as p, lpad(id, 10, '0') as o
     from table1
     where parent_id is null
  union all
  select 
     table1.parent_id, table1.id, table1.klas, 
     c1.p || '.....',
     c1.o || '.' || lpad(table1.id, 10, '0') as o
     from table1
     inner join c1 on table1.parent_id = c1.id
),
c2 (id, klas, p, o, cnt) as
(
  select c1.id, c1.klas, c1.p, c1.o, nvl(table2.cnt, 0)
  from c1
  left outer join table2 on c1.klas = table2.klas
)
select c3.p || c3.klas, (select sum(cnt) from c2 where c2.o like c3.o || '%') from c2 c3
order by c3.o

SQLFiddle - http://sqlfiddle.com/#!4/be779/97

Explanation

The first CTE is for positioning (ie the .....) and ordering (this is done by constructing column o that ensures that children come under the parent (so if the parent o is xxxx, the child will be xxxx || )

The 2nd CTE just gets the cnts - I think you can do it in the first CTE itself, but that would have been difficult to understand.

The subquery in the final query just gets the sum of a node and it's children.

Limits

  1. Note that you can go up to 10 digit IDs on this one, if you want to go over that you have to change the 10 on the lpad.
  2. The limit on depth depends on the varchar(max) - you add 11 characters (10 + one .) for each level. You can increase your depth limit if you are willing to limit your id length (a 5 digit long id will only add 6 characters for each level).
  3. For o, you actually don't need the ., but it help understand what is going on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM