具有汇总计数的Oracle分层sql

时间:2015-05-30 07:58:09

标签: sql oracle

如何在Oracle中编写SQL以返回带有rolloup计数的树视图:

SQL会返回这个:

KLAS - COUNT

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

ROOT - 10

   KLAS1 - 5

       KLAS2 - 2

       KLAS3 - 3

  KLAS4 - 5

       KLAS5 - 5

  KLAS6 - 0

       KLAS7 - 0

我有两个表,一个是结构保持,第二个是我有数据的地方。两张桌子都由klas coumn加入

复制表格的代码:

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;  

问候,伊戈尔

1 个答案:

答案 0 :(得分:0)

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

<强>解释

第一个CTE用于定位(即.....)和排序(这是通过构建列o来确保孩子们在父母之下(所以如果父o是xxxx,孩子将是xxxx) ||)

第二个CTE刚刚获得了cnts - 我认为你可以在第一个CTE本身做到这一点,但这本来很难理解。

最终查询中的子查询只获取节点及其子节点的总和。

<强>限制

  1. 请注意,您最多可以在此数字上找到10位数的ID,如果您想要更新,则必须更改lpad上的10。
  2. 深度限制取决于varchar(max) - 您为每个级别添加11个字符(10 + 1。)。如果您愿意限制ID长度,则可以增加深度限制(5位长ID只会为每个级别添加6个字符)。
  3. 对于o,你实际上并不需要。,但它有助于了解正在发生的事情。