SQL Server — обратная накопительная сумма

#sql #sql-server #cumulative-sum

#sql #sql-сервер #кумулятивная сумма

Вопрос:

У меня есть накопительная сумма, которую мне нужно отменить. Как мне это сделать в SQL Server?

Пример:

  --- ------------------- ----- 
| id|               date|value|
 --- ------------------- ----- 
| J1|2016-10-01 11:45:30|  100|
| J1|2016-10-02 11:30:30|  200|
| J1|2016-10-05 16:20:00|  400|
| J9|2016-10-06 08:35:00|  800|
| J9|2016-10-07 01:20:00|  900|
 --- ------------------- ----- 
  

Требуемый фрейм данных:

  --- ------------------- ----- --------- 
| id|               date|value|non_cum_value|
 --- ------------------- ----- --------- 
| J1|2016-10-01 11:45:30|  100|        0|
| J1|2016-10-02 11:30:30|  200|      100|
| J1|2016-10-05 16:20:00|  400|      200|
| J9|2016-10-06 08:35:00|  800|      400|
| J9|2016-10-07 01:20:00|  900|      100|
 --- ------------------- ----- --------- 
  

Мой код:

 select t1.id, t1.value, DIFFERENCE(t1.value) as 'cum_sum'
from @t t1
inner join @t t2 on t1.id >= t2.id
group by t1.id, t1.value
order by t1.id
  

Комментарии:

1. Я потерялся . , , в чем логика?

2. Если вам нужна фактическая накопительная сумма, логика ничем не отличается от того, как вы обычно это делаете; просто измените порядок ORDER BY от ASC до DESC .

Ответ №1:

Хмммм . , , вы, кажется, хотите вычесть значение из «предыдущей» строки. Это было бы:

 select t.*,
       (t.value - lag(t.val) over (order by date)) as diff
from @t;
  

Я не уверен, почему у вас есть «кумулятивная сумма» в названии. Это не помогает мне понять, что вы пытаетесь сделать.

Ответ №2:

Другая возможность :

 SELECT *, V - SUM(V) OVER(ORDER BY D ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
FROM   T
  

Предполагая, что проверенные данные :

 CREATE TABLE T (ID CHAR(2), D DATE, V FLOAT);

INSERT INTO T VALUES 
('J1', '2016-10-01 11:45:30',   100),
('J1', '2016-10-02 11:30:30',   200),
('J1', '2016-10-05 16:20:00',   400),
('J9', '2016-10-06 08:35:00',   800),
('J9', '2016-10-07 01:20:00',   900);