Хотя я согласен с комментариями, что это, вероятно, можно было бы лучше изложить, следующий sql показывает один подход к проблеме:
declare @subtract int
set @subtract = 900
;WITH CTE_Data as (
select id=1, var1= 500, var2 = 100, var3 = 200
union select id=2, var1= 800, var2 = 400, var3 = 300
union select id=3, var1= 1200, var2 = 3200, var3 = 2400
),
CTE_RunningTotals as (
select
id,
pretot = 0,
var1, var2, var3,
tot1 = var1,
tot2 = var1 + var2,
tot3 = var1 + var2 + var3
from CTE_Data where id = 1
union all
select
d.id,
pretot = rt.tot3,
d.var1, d.var2, d.var3,
tot1 = d.var1 + rt.tot3,
tot2 = d.var1 + d.var2 + rt.tot3,
tot3 = d.var1 + d.var2 + d.var3 + rt.tot3
from
CTE_Data d
join CTE_RunningTotals rt on d.id = rt.id+1
where d.id > 1
)
select
id,
var1 = case when pretot - @subtract >= 0 then var1
else case when tot1 - @subtract > 0 then tot1 - @subtract else 0 end
end,
var2 = case when tot1 - @subtract >= 0 then var2
else case when tot2 - @subtract > 0 then tot2 - @subtract else 0 end
end,
var3 = case when tot2 - @subtract >= 0 then var3
else case when tot3 - @subtract >0 then tot3 - @subtract else 0 end
end
from CTE_RunningTotals
возвращает
id var1 var2 var3
1 0 0 0
2 700 400 300
3 1200 3200 2400
CTE_Data isпросто входные данные, вы можете изменить это для вашей исходной таблицы.
CTE_RunningTotals содержит необработанные данные плюс промежуточный итог всех значений в таблице до текущей строки / столбца.
Если предыдущая строка / столбец равна нулю (т. Е. Значение вычитания больше, чем текущая сумма), значение вычитания берется из текущего значения, в противном случае возвращается значение данных.
Возможно, вам будет прощечтобы понять, что происходит, если вы select * from CTE_RunningTotals
после деклараций CTE, чтобы вы могли видеть работу.