如何將葉子節(jié)點(diǎn)的數(shù)據(jù)合計(jì)到父節(jié)點(diǎn) by Oracle 10g
原文地址在這里:【難題】如何將葉子節(jié)點(diǎn)的數(shù)據(jù)合計(jì)到父節(jié)點(diǎn),原文已經(jīng)不能回復(fù)了,在這里寫下解法。
題目簡單描述如下:
有數(shù)據(jù)表結(jié)構(gòu)如下,只有葉子節(jié)點(diǎn)有數(shù)據(jù):
id parentId name amount 1 成本 2 1 工資 3 2 基本工資 1000 4 2 獎(jiǎng)金 200 5 1 保險(xiǎn) 400
現(xiàn)在想統(tǒng)計(jì)處父節(jié)點(diǎn)合計(jì)數(shù) ,如下:
id name amount 1 成本 1600 //2 + 5 2 工資 1200 //3 + 4 3 基本工資 1000 4 獎(jiǎng)金 200 5 保險(xiǎn) 400
作者要求是Oracle數(shù)據(jù)庫。
由于功力不夠求助了ITPUB上的大牛,也得到了精妙的回復(fù),在這里記錄一下:
為節(jié)省篇幅,使用CTE語法構(gòu)建臨時(shí)表,不再建表了:
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 , '獎(jiǎng)金' , 200 from dual union all select 5,1 , '保險(xiǎn)' , 400 from dual ) select * from tmp
ID PARENTID NAME AMOUNT ---------------------- ---------------------- -------- ---------------------- 1 成本 2 1 工資 3 2 基本工資 1000 4 2 獎(jiǎng)金 200 5 1 保險(xiǎn) 400
首先是來自2樓newkid的解法:
SELECT root_id,SUM(amount)
FROM (
select CONNECT_BY_ROOT(id) root_id,amount
from tmp
WHERE CONNECT_BY_ISLEAF=1
CONNECT BY PRIOR id = parentid
)
GROUP BY root_id;
然后是3樓dingjun123的解法:
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 子句自根節(jié)點(diǎn)/分支節(jié)點(diǎn)往葉子結(jié)點(diǎn)搜索,找出不同的根節(jié)點(diǎn)/分支節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑再求和,修改一下newkid的子查詢并查看一下結(jié)果集就比較明了:
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)的節(jié)點(diǎn)id,leaf_id就是葉子節(jié)點(diǎn)的id,用圖來幫助分析:
可以看到id=1的節(jié)點(diǎn),也就是根節(jié)點(diǎn)的值等于三個(gè)葉子節(jié)點(diǎn)的值的總和,葉子節(jié)點(diǎn)的值是明確的。
下一篇將會(huì)使用SQL Server遞歸CTE語句對該問題求解,請留意。
浙公網(wǎng)安備 33010602011771號