源动力

程序在于积累和思考
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

oracle中如何将叶子节点的数据累加到父节点

Posted on 2011-04-13 12:26  老K的幸福生活  阅读(2171)  评论(0编辑  收藏  举报

假设有数据表结构如下,只有叶子节点有数据:

id  parentId    name        amount
1               成本     
2    1          工资   
3    2          基本工资    1000  
4    2          奖金        200
5    1          保险        400

现在想统计处父节点合计数 ,如下:

id      name       amount
1       成本       1600    //2 + 5
2       工资       1200    //3 + 4
3       基本工资   1000  
4       奖金       200
5       保险       400

使用CTE语法构建临时表如下:

with tmp as (
  select 1 as id , null as parentid , '成本' as name , null as amount from dual union all
  select 2,1 , '工资', null from dual union all
  select 3,2 , '基本工资', 1000 from dual union all
  select 4,2 , '奖金' , 200 from dual union all
  select 5,1 , '保险' , 400 from dual
)
select * from tmp; 
ID                     PARENTID               NAME     AMOUNT                 
---------------------- ---------------------- -------- ----------------------
1                                             成本                           
2                      1                      工资                           
3                      2                      基本工资  1000                  
4                      2                      奖金     200                    
5                      1                      保险     400  

解法一:

select root_id,root_name,sum(amount)
from (select connect_by_root(id) root_id,connect_by_root(name) root_name,amount from tmp where connect_by_isleaf=1 connect by prior id = parentid)
group by root_id,root_name
order by root_id;

解法二(使用内查询方式):

select id,parentid,name,
  (select sum(amount) from tmp a start with a.id=b.id connect by prior a.id=a.parentid ) sum_sal
from tmp b order by 1;

基本思路都是利用 connect by 子句自根节点/分支节点往叶子结点搜索,找出不同的根节点/分支节点到叶子节点的路径再求和,修改一下解法一的子查询并查看一下结果集:

select connect_by_root(id) start_id,id leaf_id,amount  
from tmp where connect_by_isleaf=1 connect by prior id = parentid;
  START_ID    LEAF_ID     AMOUNT
---------- ---------- ----------
         1          3       1000
         1          4        200
         1          5        400
         2          3       1000
         2          4        200
         3          3       1000
         4          4        200
         5          5        400

start_id 就是开始查找(不是start with)的节点id,leaf_id就是叶子节点的id,可以看到id=1的节点,也就是根节点的值等于三个叶子节点的值的总和,叶子节点的值是明确的。