问题
I have a query for selecting amounts per department in a tree-like structure. I want to display the sum amount of the children on their respective parent.
Is it possible to archive this in a query without using a cursor?
Below is a resultset of the data to sum up. A full sample can also be found on sqlfiddle.
Results:
| DEPARTMENT_ID | PARENT_DEP_ID | DEPARTMENT | AMOUNT |
|---------------|---------------|----------------|-----------------|
| 1 | 0 | 1 | 0 |
| 7 | 1 | 11 | 0 |
| 34 | 7 | 111 | 0 |
| 120 | 34 | 1111 | 0 |
| 402 | 120 | 111101 | 0 |
| 651 | 402 | 11110101/10000 | 227470.72339635 |
| 651 | 402 | 11110101/10000 | 52255.99610869 |
| 651 | 402 | 11110101/10000 | 4437.15281795 |
| 651 | 402 | 11110101/10000 | 4552.70289465 |
| 651 | 402 | 11110101/10000 | 8510.61790448 |
| 651 | 402 | 11110101/10000 | 8266.08 |
| 651 | 402 | 11110101/10000 | 9968.16 |
| 651 | 402 | 11110101/10000 | 242.58 |
| 403 | 120 | 111102 | 0 | <= this is where i
| 652 | 403 | 11110201/10005 | 120384.7842412 | want to have my
| 652 | 403 | 11110201/10005 | 488733.59476206 | sum from the
| 652 | 403 | 11110201/10005 | 2318.6573888 | child items
| 652 | 403 | 11110201/10005 | 23690.22829273 |
| 652 | 403 | 11110201/10005 | 38321.261680815 |
| 652 | 403 | 11110201/10005 | 6199.56 |
| 652 | 403 | 11110201/10005 | 7476.12 |
| 652 | 403 | 11110201/10005 | 161.92 |
回答1:
This will get the full report
SELECT t1.DEPARTMENT_ID
, t1.PARENT_DEP_ID
, t1.DEPARTMENT
, Sum(t2.Amount) Amount
FROM TREE_DATA t1
INNER JOIN TREE_DATA t2
ON t1.DEPARTMENT = SUBSTR(t2.DEPARTMENT, 1, LENGTH(t1.DEPARTMENT))
WHERE t1.Amount = 0
GROUP BY t1.DEPARTMENT_ID, t1.PARENT_DEP_ID, t1.DEPARTMENT
UNION ALL
SELECT DEPARTMENT_ID
, PARENT_DEP_ID
, DEPARTMENT
, Amount
FROM TREE_DATA
WHERE Amount > 0
ORDER BY DEPARTMENT
The first query get the rolling sum by hacking the structure of the Department name for the oens without the amounts, the second one get the leafs.
The first query cannot show the leafs, as they will get grouped.
I haven't found any column combination to get the same order, the leafs seems to be unordered.
SQLFiddle demo
I've tried to write a recursive CTE, but it's not possible to have aggregate function, such as SUM in it.
回答2:
with rec(parent_dep_id, department_id, depth) as (
select cast(null as int), 403, 0 from dual
union all
select rec.department_id, t.department_id, depth+1
from rec
, tree_data t
where depth<100
and rec.department_id = t.parent_dep_id
) select sum(t.amount)
from rec
join tree_data t
on rec.department_id = t.department_id
One can avoid the final join on tree_data by including amount in rec.
来源:https://stackoverflow.com/questions/23607020/how-can-i-sum-up-data-in-tree-like-structure-in-sql-from-children-to-parent