I have a table.
SELECT * INTO #tmp
FROM (
SELECT 1 AS [ID], 20200312 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 480.00 AS [ValueC], 4906 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200313 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1440.00 AS [ValueC], 3466 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200314 AS [date], 0 AS [ValueA], 1000.00 AS [ValueB], 0.00 AS [ValueC], 4466 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200318 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1056.00 AS [ValueC], 3410 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200319 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 864.00 AS [ValueC], 2546 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200320 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1296.00 AS [ValueC], 1250 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200321 AS [date], 0 AS [ValueA], 4000.00 AS [ValueB], 624.00 AS [ValueC], 4626 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200324 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1152.00 AS [ValueC], 3474 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200325 AS [date], 3474 AS [ValueA], 0.00 AS [ValueB], 2718.00 AS [ValueC], 756 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200330 AS [date], 0 AS [ValueA], 6000.00 AS [ValueB], 1080.00 AS [ValueC], 5676 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200401 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1920.00 AS [ValueC], 2756 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200403 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1920.00 AS [ValueC], 836 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200407 AS [date], 0 AS [ValueA], 3000.00 AS [ValueB], 0.00 AS [ValueC], 3836 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200408 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 2448.00 AS [ValueC], 1388 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200413 AS [date], 0 AS [ValueA], 4000.00 AS [ValueB], 0.00 AS [ValueC], 5388 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200415 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1920.00 AS [ValueC], 3468 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200417 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1920.00 AS [ValueC], 1548 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200420 AS [date], 0 AS [ValueA], 1000.00 AS [ValueB], 1920.00 AS [ValueC], 628 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200426 AS [date], 0 AS [ValueA], 4000.00 AS [ValueB], 0.00 AS [ValueC], 4628 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200515 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 3840.00 AS [ValueC], 788 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200525 AS [date], 0 AS [ValueA], 3000.00 AS [ValueB], 1920.00 AS [ValueC], 1868 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200601 AS [date], 0 AS [ValueA], 2000.00 AS [ValueB], 1080.00 AS [ValueC], 2788 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200608 AS [date], 0 AS [ValueA], 1000.00 AS [ValueB], 1920.00 AS [ValueC], 1868 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200615 AS [date], 0 AS [ValueA], 2000.00 AS [ValueB], 0.00 AS [ValueC], 3868 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200622 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1920.00 AS [ValueC], 1948 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200706 AS [date], 0 AS [ValueA], 2000.00 AS [ValueB], 1920.00 AS [ValueC], 2028 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200713 AS [date], 0 AS [ValueA], 2000.00 AS [ValueB], 0.00 AS [ValueC], 4028 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200720 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 3000.00 AS [ValueC], 1028 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200727 AS [date], 0 AS [ValueA], 3000.00 AS [ValueB], 0.00 AS [ValueC], 4028 AS [NewColumn] UNION ALL
SELECT 1 AS [ID], 20200803 AS [date], 0 AS [ValueA], 0.00 AS [ValueB], 1920.00 AS [ValueC], 2108 AS [NewColumn]
) t;
[NewColumn] is the desired output
SELECT [ID], [date], [ValueA], [ValueB], [ValueC], [NewColumn]
FROM #tmp
order by [date]
Based on values for columns A,B and C the only value that i can calculate is where the date is 20200325 and is calculated based on formula below.
update #tmp
set [NewColumn] = ValueA+ValueB-ValueC
where date = 20200325
So the value is 756
all others rows are calculated based on the previous row ex:
[NewColumn](for date 20200330) = [NewColumn](for date 20200325)+ValueA+ValueB-ValueC
X = 756 + 0 + 6000 - 1080
X = 5676
and so on...
Is there a way to achive this in sql through an update statement
PS. I need to update before 20200325 as well as after that date
Assuming that you are runnin SQL-Server, as the syntax suggests, you could use an updateble cte and window functions:
with cte as (
select
NewColumn,
sum(ValueA + ValueB - ValueC) over(partition by id order by date) NewVal
from #tmp
where date >= 20200325
)
update cte set NewColumn = NewVal
ID | date | ValueA | ValueB | ValueC | NewColumn -: | -------: | -----: | :------ | :------ | --------: 1 | 20200312 | 0 | 0.00 | 480.00 | 4906 1 | 20200313 | 0 | 0.00 | 1440.00 | 3466 1 | 20200314 | 0 | 1000.00 | 0.00 | 4466 1 | 20200318 | 0 | 0.00 | 1056.00 | 3410 1 | 20200319 | 0 | 0.00 | 864.00 | 2546 1 | 20200320 | 0 | 0.00 | 1296.00 | 1250 1 | 20200321 | 0 | 4000.00 | 624.00 | 4626 1 | 20200324 | 0 | 0.00 | 1152.00 | 3474 1 | 20200325 | 3474 | 0.00 | 2718.00 | 756 1 | 20200330 | 0 | 6000.00 | 1080.00 | 5676 1 | 20200401 | 0 | 0.00 | 1920.00 | 3756 1 | 20200403 | 0 | 0.00 | 1920.00 | 1836 1 | 20200407 | 0 | 3000.00 | 0.00 | 4836 1 | 20200408 | 0 | 0.00 | 2448.00 | 2388 1 | 20200413 | 0 | 4000.00 | 0.00 | 6388 1 | 20200415 | 0 | 0.00 | 1920.00 | 4468 1 | 20200417 | 0 | 0.00 | 1920.00 | 2548 1 | 20200420 | 0 | 1000.00 | 1920.00 | 1628 1 | 20200426 | 0 | 4000.00 | 0.00 | 5628 1 | 20200515 | 0 | 0.00 | 3840.00 | 1788 1 | 20200525 | 0 | 3000.00 | 1920.00 | 2868 1 | 20200601 | 0 | 2000.00 | 1080.00 | 3788 1 | 20200608 | 0 | 1000.00 | 1920.00 | 2868 1 | 20200615 | 0 | 2000.00 | 0.00 | 4868 1 | 20200622 | 0 | 0.00 | 1920.00 | 2948 1 | 20200706 | 0 | 2000.00 | 1920.00 | 3028 1 | 20200713 | 0 | 2000.00 | 0.00 | 5028 1 | 20200720 | 0 | 0.00 | 3000.00 | 2028 1 | 20200727 | 0 | 3000.00 | 0.00 | 5028 1 | 20200803 | 0 | 0.00 | 1920.00 | 3108
What you describe is:
select t.*, sum(valuea + valueb - valuec) over (partition by id order by date)
from tmp t
where date >= '20200325'
order by id, date;
However, this does not return the values that you specify. It returns:
ID date ValueA ValueB ValueC NewColumn (No column name)
1 20200325 3474 0.00 2718.00 756 756.00
1 20200330 0 6000.00 1080.00 5676 5676.00
1 20200401 0 0.00 1920.00 2756 3756.00
1 20200403 0 0.00 1920.00 836 1836.00
1 20200407 0 3000.00 0.00 3836 4836.00
1 20200408 0 0.00 2448.00 1388 2388.00
1 20200413 0 4000.00 0.00 5388 6388.00
1 20200415 0 0.00 1920.00 3468 4468.00
1 20200417 0 0.00 1920.00 1548 2548.00
1 20200420 0 1000.00 1920.00 628 1628.00
Here is a db<>fiddle.
I suspect that you don't want to hardcode 20200325, but you just want a non-zero value of valueA
. In that case, you can assign groups using window functions:
select t.*, sum(valuea + valueb - valuec) over (partition by id, grp order by date)
from (select t.*,
sum(case when valueA > 0 then 1 else 0 end) over (partition by id order by date) as grp
from tmp t
) t
where grp > 0
order by id, date;
You can incorporate this into an update
, if you like:
with toupdate as (
select t.*,
sum(valuea + valueb - valuec) over (partition by id order by date) as new_newcolumn
from tmp t
where date >= '20200325'
)
update toupdate
set newcolumn = new_newcolumn
where newcolumn <> new_newcolumn;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.