累计将去年期末余额的销售额与当年的期初余额相加

时间:2016-06-14 08:03:01

标签: sql oracle

我正在尝试累计增加去年收盘余额的销售额,将其推向第一个月,并按月继续增加。例如,如果我们有以下数据:

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

注意,对于Year = 2015,该年度的期末余额为月= 12余额,在这种情况下,对于group2为89,对于group1为20。如果我们在2016年,我希望累积查询返回如下内容:

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

这看起来需要涉及分析函数sum()over(partition by .... order by ...)

但我还没有找到正确的方法来做到这一点。

提前致谢。

1 个答案:

答案 0 :(得分:1)

Oracle安装程序

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;

<强>查询

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;

查询 - 没有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;

<强>输出

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