Рассмотрим следующую таблицу:
select id, val, newval from test1;
id | val | newval
----+-----+--------
1 | 1 | 0
2 | 2 | 0
3 | 5 | 0
4 | 9 | 0
5 | 10 | 0
Я ищу запрос на обновление, который может последовательно обновлять значения в столбце newval , где обновленное значение - это разница между val и val.prev (значение val в предыдущей строке) плюс значение UDATED newval из предыдущей строки.Результат будет:
select id, val, newval from test1;
id | val | newval
----+-----+--------
1 | 1 | 0 = set to zero since result would be NULL (no previous row exists)
2 | 2 | 1 = 2 - 1 + 0
3 | 5 | 4 = 5 - 2 + 1
4 | 9 | 8 = 9 - 5 + 4
5 | 10 | 9 = 10 - 9 + 8
^ - uses updated value of newval
Я подошел к решению со следующим:
WITH tt AS (
SELECT id, COALESCE(val - lag(val) OVER w + lag(newval) OVER w,0) as nv
FROM test1
WINDOW w AS (ORDER BY id)
)
UPDATE test1 SET newval = tt.nv FROM tt
WHERE test1.id = tt.id;
, который дает следующий результат:
select id, val, newval from test1;
id | val | newval
----+-----+--------
1 | 1 | 0
2 | 2 | 1 = 2 - 1 + 0
3 | 5 | 3 = 5 - 2 + 0
4 | 9 | 4 = 9 - 5 + 0
5 | 10 | 1 = 10 - 9 + 0
^ - uses old value of newval
, но этоРешение не использует обновленные значения newval .Он использует старые значения.
Я знаю, что могу написать функцию для циклического прохождения таблицы по одной строке за раз, но из того, что я прочитал, этот метод будет неэффективным и обычно не рекомендуется.Мое реальное приложение более сложное и включает большие таблицы, поэтому эффективность важна.