Reputation: 3496
I am trying to cumulatively add sales from last years closing balance bringing it forward to first month and continuing like this from month to month. For instance if we have the following data:
select 4 id, 'A' name, 'group1' group, '2015' year, '10' month, 20 sales from dual union all
select 5 id, 'C' name,'group2' group, '2015' year, '12' month, 89 sales from dual union all
select 13 id,'B' name, 'group2' group, '2016' year, '01' month, 10 sales from dual union all
select 14 id,'A' name, 'group3' group, '2016' year, '02' month, 8 sales from dual union all
select 15 id,'B' name, 'group1' group, '2016' year, '02' month, 16 sales from dual union all
select 16 id,'D' name,'group2' group, '2016' year, '04' month, 15 sales from dual union all
select 17 id,'D' name,'group4' group, '2016' year, '05' month, 23 sales from dual union all
select 18 id,'D' name,'group3' group, '2016' year, '06' month, 39 sales from dual union all
select 19 id,'D' name,'group3' group, '2016' year, '07' month, 45 sales from dual union all
select 20 id,'D' name,'group3' group, '2016' year, '08' month, 12 sales from dual union all
select 21 id,'D' name,'group4' group, '2016' year, '09' month, 20 sales from dual union all
select 22 id,'D' name,'group3' group, '2016' year, '10' month, 4 sales from dual union all
select 23 id,'D' name,'group3' group, '2016' year, '11' month, 98 sales from dual union all
select 24 id,'D' name,'group4' group, '2016' year, '12' month, 70 sales from dual
Note, for Year=2015 the closing balance for that year is month=12 balance which in this case is 89 for group2 and 20 for group1. If we are in 2016, I want the cumulative query to return something like this:
year, month, group, opening_balance, closing_balance
2016 01 group2 89 99 (89+10)
2016 02 group3 0 8 (0+8)
2016 02 group1 20 36 (20 + 16)
2016 04 group2 99 114 (99 + 15)
2016 05 group4 0 23 (0 + 23 - note group4 has no prior balances)
2016 06 group3 8 47 (8 + 39)
2016 07 group3 47 92 (47 + 45)
and so on
This looks like it needs involving the analytical function sum() over (partition by .... order by ... )
But I haven't figured out the correct way to do this.
Thanks in advance.
Upvotes: 0
Views: 82
Reputation: 168701
Oracle Setup:
CREATE TABLE sales ( id, name, grp, year, month, sales ) AS
SELECT 4, 'A', 'group1', '2015', '10', 20 FROM DUAL UNION ALL
SELECT 5, 'C', 'group2', '2015', '12', 89 FROM DUAL UNION ALL
SELECT 13, 'B', 'group2', '2016', '01', 10 FROM DUAL UNION ALL
SELECT 14, 'A', 'group3', '2016', '02', 8 FROM DUAL UNION ALL
SELECT 15, 'B', 'group1', '2016', '02', 16 FROM DUAL UNION ALL
SELECT 16, 'D', 'group2', '2016', '04', 15 FROM DUAL UNION ALL
SELECT 17, 'D', 'group4', '2016', '05', 23 FROM DUAL UNION ALL
SELECT 18, 'D', 'group3', '2016', '06', 39 FROM DUAL UNION ALL
SELECT 19, 'D', 'group3', '2016', '07', 45 FROM DUAL UNION ALL
SELECT 20, 'D', 'group3', '2016', '08', 12 FROM DUAL UNION ALL
SELECT 21, 'D', 'group4', '2016', '09', 20 FROM DUAL UNION ALL
SELECT 22, 'D', 'group3', '2016', '10', 4 FROM DUAL UNION ALL
SELECT 23, 'D', 'group3', '2016', '11', 98 FROM DUAL UNION ALL
SELECT 24, 'D', 'group4', '2016', '12', 70 FROM DUAL;
Query:
SELECT *
FROM (
SELECT year,
month,
grp,
COALESCE(
SUM( sales ) OVER ( PARTITION BY grp
ORDER BY dt
RANGE BETWEEN UNBOUNDED PRECEDING
AND INTERVAL '1' MONTH PRECEDING
),
0
) AS opening_balance,
SUM( sales ) OVER ( PARTITION BY grp
ORDER BY dt
RANGE BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW
) AS closing_balance
FROM (
SELECT s.*,
TO_DATE( year || month, 'YYYYMM' ) AS dt
FROM sales s
)
)
WHERE year = 2016
ORDER BY year, month, grp;
Query - Alternative without RANGE BETWEEN
:
SELECT *
FROM (
SELECT year,
month,
grp,
SUM( sales ) OVER ( PARTITION BY grp
ORDER BY year, month )
- sales AS opening_balance,
SUM( sales ) OVER ( PARTITION BY grp
ORDER BY year, month
) AS closing_balance
FROM sales
)
WHERE year = 2016
ORDER BY year, month, grp;
Output:
YEAR MO GRP OPENING_BALANCE CLOSING_BALANCE
---- -- ------ --------------- ---------------
2016 01 group2 89 99
2016 02 group1 20 36
2016 02 group3 0 8
2016 04 group2 99 114
2016 05 group4 0 23
2016 06 group3 8 47
2016 07 group3 47 92
2016 08 group3 92 104
2016 09 group4 23 43
2016 10 group3 104 108
2016 11 group3 108 206
2016 12 group4 43 113
Upvotes: 1