计算数据分区的运行总计

时间:2015-09-23 13:05:36

标签: sql sql-server tsql running-total

我有一个名为#t1和三列的表。 CODE,Column1和Column2。

        create table #t1 (
        CODE  NVARCHAR(20),
        COLUMN1  NUMERIC(18,2),
        COLUMN2  NUMERIC(18,2) 
                              )

我有一些数据:

      INSERT INTO #t1 (CODE,COLUMN1,COLUMN2)
VALUES ('432', 0,100),
       ('TOTAL FOR 432',0,100),
       ('4320001',0,250),
       ('4320001',50,0),
       ('4320001',0,140),
       ('4320001',300,0),
       ('TOTAL FOR 4320001',350,390),
       ('432002',200,0),
       ('432002',0,100),
       ('TOTAL FOR 432002',200,100)




       drop table #t1

我想要4列(名为BALANCE)。余额必须是表示每组数据的两列(Column1 - Column2)之间的运行总计的列。对于每个组,总数必须从零开始。

输出:

             CODE                    COLUMN1        COLUMN2        BALANCE
             432                      0.00           100.00         -100
   TOTAL     432                      0.00           100.00         -100
         4320001                      0.00           250.00         -250   
         4320001                     50.00             0.00         -200
         4320001                      0.00           140.00         -340
         4320001                    300.00             0.00          -40
   TOTAL 4320001                    350.00           390.00          -40
          432002                    200.00             0.00          200
          432002                      0.00           100.00          100
   TOTAL  432002                    200.00           100.00          100

总计432后,它再次开始计算总计4320001和agian总计432002 ..... 我怎样才能得到这个结果?

我正在使用MS SQL SERVER 2014

SQL FIDDLE

编辑: 到目前为止我已经尝试过了(但这并不好):

 SUM(sum(column1)-sum(column2)) OVER(ORDER BY code rows UNBOUNDED PRECEDING) AS SALDO

2 个答案:

答案 0 :(得分:2)

根据你的输出:)

  DECLARE @t1 TABLE (
  CODE nvarchar(20),
  COLUMN1 numeric(18, 2),
  COLUMN2 numeric(18, 2)
)

INSERT INTO @t1 (CODE, COLUMN1, COLUMN2)
  VALUES ('432', 0, 100),
  ('TOTAL FOR 432', 0, 100),
  ('4320001', 0, 250),
  ('4320001', 50, 0),
  ('4320001', 0, 140),
  ('4320001', 300, 0),
  ('TOTAL FOR 4320001', 350, 390),
  ('432002', 200, 0),
  ('432002', 0, 100),
  ('TOTAL FOR 432002', 200, 100)

-- CTE
;
WITH CTE
AS (SELECT
  *,
  ROW_NUMBER() OVER (ORDER BY @@rowcount) RowNum -- Order as per the input
FROM @t1)
-- get from CTE
SELECT
  *,
  SUM(COLUMN1 - COLUMN2) OVER (PARTITION BY code ORDER BY RowNum) AS Balance --sum using PARTITION
FROM CTE
ORDER BY RowNum

答案 1 :(得分:0)

您可以使用以下查询来获取预期的结果集:

SELECT CODE_NAME, COLUMN1, COLUMN2, BALANCE
FROM (
  SELECT CODE, CODE AS CODE_NAME, 1 AS ORD, COLUMN1, COLUMN2,
         SUM(COLUMN1 - COLUMN2) 
         OVER (PARTITION BY CODE ORDER BY id) AS BALANCE
  FROM t1

  UNION ALL

  SELECT CODE, CONCAT ('TOTAL FOR ', CODE) AS CODE_NAME, 2 AS ORD,
         SUM(COLUMN1), SUM(COLUMN2), 
         SUM(COLUMN1 - COLUMN2) AS BALANCE
  FROM t1
  GROUP BY CODE
)  AS t
ORDER BY CODE, ORD

以上假设有一个自动增量PK列id,用于定义顺序。它还假设总聚合不存储在原始表中。

使用SUM聚合函数的窗口版本可以轻松计算运行总计。 PARTITION BY子句中的OVER会导致按CODE切片计算总计。 ORDER BY id子句中的OVER是导致运行总计算的原因。

总聚合数由单独的查询计算。 ORD字段可帮助我们在执行CODE后正确排序UNION ALL个切片。

Demo here