Sql обновление на основе предыдущего ряда - PullRequest
0 голосов
/ 31 марта 2020

У меня есть таблица.

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] - желаемый вывод

SELECT [ID], [date], [ValueA], [ValueB], [ValueC], [NewColumn]
FROM #tmp
order by [date]

На основе значений для столбцов A, B и C единственное значение, которое я Можно вычислить, где дата 20200325 и рассчитывается по формуле ниже.

update #tmp
set [NewColumn] = ValueA+ValueB-ValueC
where date = 20200325

Таким образом, значение равно 756

Все остальные строки рассчитываются на основе предыдущей строки, например:

[NewColumn](for date 20200330) = [NewColumn](for date 20200325)+ValueA+ValueB-ValueC
X = 756 + 0 + 6000 - 1080
X = 5676

и так далее ...

Есть ли способ добиться этого в sql с помощью оператора обновления

PS. Мне нужно обновить до 20200325, а также после этой даты

Ответы [ 2 ]

0 голосов
/ 31 марта 2020

Что вы описываете:

select t.*, sum(valuea + valueb - valuec) over (partition by id order by date)
from tmp t
where date >= '20200325'
order by id, date;

Однако это не возвращает указанные вами значения. Он возвращает:

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

Здесь - это дБ <> скрипка.

Я подозреваю, что вы не хотите жестко кодировать 20200325, но вы просто хотите не Нулевое значение valueA. В этом случае вы можете назначать группы, используя оконные функции:

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;

Вы можете включить это в update, если хотите:

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;
0 голосов
/ 31 марта 2020

Если вы работаете на SQL -Server, как подсказывает синтаксис, вы можете использовать обновляемые функции cte и window:

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

Демонстрация на DB Fiddle :

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...