【问题标题】:Calculate Incremental sum from running total Column从运行总列计算增量总和
【发布时间】:2018-01-12 07:58:01
【问题描述】:

我的 SQL Server 表中已经有一个运行总计列,如下所示

ID Value
1  1000
2  2000
3  3000
4  4000
5  5000

我需要获取值的增量总和(不确定它是否正确),例如:1000 + (1000-2000) + (2000-3000) + (3000-4000) + (4000 -5000) = 5000

最终结果应该是这样的,这样我才能得到 INC_Sum 列的总和

ID Value INC_Sum
1  1000   1000
2  2000   1000
3  3000   1000
4  4000   1000
5  5000   1000

我上面给出的那个是一个例子,我的表有数百万的更复杂的值。我正在运行 SQL Server 2008 R2,有人可以帮我解决这个问题吗?

【问题讨论】:

标签: sql sql-server tsql sql-server-2008-r2


【解决方案1】:

你可以使用lag():

select id, value,
       (value - lag(value, 1, 0) over (order by id)) as inc_sum
from t;

请注意,这使用了滞后的 3 参数形式。第二个参数是偏移量(要返回的行数)。第三个是默认值。

在 SQL Server 2012 之前,您将使用 outer apply

select t.id, t.value,
       (t.value - coalesce(t2.value, 0) as inc_sum
from t outer apply
     (select top 1 t2.*
      from t t2
      where t2.id < t.id
      order by t2.id desc
     ) t2;

或者,如果您知道id 中没有空白(这可能不是一个合理的假设:

select t.id, t.value,
       (t.value - coalesce(t2.value, 0) as inc_sum
from t left join
     t t2
     on t2.id = t.id - 1;

【讨论】:

  • LAG 在 2008 R2 中可用吗?
【解决方案2】:

我之前在这里看到过这个回答:

http://sqlfiddle.com/#!3/4e9e4

CREATE TABLE t
    ([id] int, [SomeNumt] int);

INSERT INTO t
    ([id], [SomeNumt])
VALUES
    (1, 10),
    (2, 12),
    (3, 3),
    (4, 15),
    (5, 23);

SELECT t1.id,
       t1.SomeNumt,
       SUM(t2.SomeNumt) AS SUM
FROM t t1
INNER JOIN t t2 ON t1.id >= t2.id
GROUP BY t1.id,
         t1.SomeNumt
ORDER BY t1.id

【讨论】:

    【解决方案3】:
    SELECT t1.id,
       t1.SomeNum,
       t1.SomeNum - ISNULL(t2.SomeNum, 0) AS Delta
    FROM t t1
    LEFT OUTER JOIN t t2 ON t2.id = t1.id - 1
    ORDER BY t1.id
    

    或者,如果 id 列有间隙:

    SELECT t1.id,
       t1.SomeNum,
       t1.SomeNum - ISNULL(t2.SomeNum, 0) AS Delta
    FROM t t1
    LEFT OUTER JOIN t t2 ON t2.id = (SELECT MAX(t.id) FROM t WHERE t.id < t1.id)
    ORDER BY t1.id
    

    测试:

    create table t(id int, somenum int)
    insert into t select 1,1 
    insert into t select 2,2 
    insert into t select 3,3 
    insert into t select 5,4 
    

    【讨论】:

      【解决方案4】:

      使用outer apply()根据id的顺序获取上一个值,并使用isnull()0替换为null值:

      select 
          t.id
        , t.value
        , INC_Sum = t.value - isnull(x.previous_value,0)
      from t
        outer apply (
          select top 1 
              previous_value = i.value
          from t as i
          where i.id < t.id
          order by i.id desc
          ) x
      

      rextester 演示:http://rextester.com/SYV5992

      返回:

      +----+-------+---------+
      | id | value | INC_Sum |
      +----+-------+---------+
      |  1 |  1000 |    1000 |
      |  2 |  2000 |    1000 |
      |  3 |  3000 |    1000 |
      |  4 |  4000 |    1000 |
      |  5 |  5000 |    1000 |
      +----+-------+---------+
      

      【讨论】:

        猜你喜欢
        • 2017-04-18
        • 1970-01-01
        • 1970-01-01
        • 2020-06-30
        • 1970-01-01
        • 2013-04-17
        • 1970-01-01
        • 1970-01-01
        • 2017-10-04
        相关资源
        最近更新 更多