2016-06-14 71 views
0

我正在尝试累积增加上年度期末余额的销售额,并将其转入第一个月,并按月逐月继续。举例来说,如果我们有如下的数据:累计合计从上年度期末余额到当前年度期初余额的销售额

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 

注意,对于年份= 2015该年度的期末余额为一个月= 12的平衡,在这种情况下是89组2和20组1。如果我们是在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 

这看起来像它需要涉及的分析功能和()上(通过分区.... ORDER BY ...)

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

在此先感谢。

+0

你为什么要储存年份和月份为两列文本?最好将它作为一个单独的'DATE'列存储,如果你需要单独的组件,你可以使用'EXTRACT(YEAR FROM sale_date)'或'TO_CHAR(sale_date,'MM')'。 – MT0

+0

您有'group3'开头余额为99 - 但这不会反映在示例数据中。 99从哪里来? – MT0

+0

MT0你是对的。修复。感谢您注意 – bytebiscuit

回答

1

甲骨文设置

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 
+0

在无限上传范围 和区间'1'月前导出的错误 – bytebiscuit

+0

说你有一个“错误”对于计算错误是什么 - 错误是什么? – MT0

+0

@bytebiscuit更新了示例输入和输出。但是,您所说的代码有一个错误,并且它在我的系统上运行(Oracle 11.2.0.1)。 – MT0