Sql 按顺序更新列值,其中新值基于';以前的';一行

Sql 按顺序更新列值,其中新值基于';以前的';一行,sql,postgresql,window-functions,postgresql-9.6,Sql,Postgresql,Window Functions,Postgresql 9.6,考虑下表: 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值)之间的差值加上前一行中的UD

考虑下表:

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值。它使用旧的值


我知道我可以编写一个函数,一次循环表中的一行,但从我所读到的来看,这种方法效率低下,通常不鼓励使用。我的实际应用程序更复杂,涉及大型表,因此效率非常重要。

我很确定您的逻辑可以简化为:

select id, val, (val - 1) as newval
from t;
为什么??您正在获取上一行中
val
val
之间差值的累计和。累积差值最终是最近的值减去第一个值

第一个值是
1
。上面的硬编码表示该值。调整第一个值的逻辑很容易:

select id, val,
       (val - first_value(val) over (order by id) as newval
from t;

我很确定,你的逻辑归结为:

select id, val, (val - 1) as newval
from t;
为什么??您正在获取上一行中
val
val
之间差值的累计和。累积差值最终是最近的值减去第一个值

第一个值是
1
。上面的硬编码表示该值。调整第一个值的逻辑很容易:

select id, val,
       (val - first_value(val) over (order by id) as newval
from t;

这是一个微不足道的例子。我不是只为这个问题寻找解决方案。最后,我正在寻找一种按顺序更新列值的解决方案(即,当下一列值取决于上一行中更新的值时)。提供的示例表和计算有助于解释我的问题。不要专注于正在进行的数学运算。@iamthebull。这回答了您提出的问题。事实上,它只是一个微不足道的例子,因为这正是你所要求的。如果你有不同的问题,我建议你问一个新问题。另一方面,我认为你应该接受这一点,因为这是迄今为止解决你问题的最简单、最有效的方法。我重复一遍。。。我的问题是关于按顺序更新表中的行,其中新行值取决于前一行的更新值(请参见问题标题)。你对此有什么意见吗?这是一个微不足道的例子。我不是只为这个问题寻找解决方案。最后,我正在寻找一种按顺序更新列值的解决方案(即,当下一列值取决于上一行中更新的值时)。提供的示例表和计算有助于解释我的问题。不要专注于正在进行的数学运算。@iamthebull。这回答了您提出的问题。事实上,它只是一个微不足道的例子,因为这正是你所要求的。如果你有不同的问题,我建议你问一个新问题。另一方面,我认为你应该接受这一点,因为这是迄今为止解决你问题的最简单、最有效的方法。我重复一遍。。。我的问题是关于按顺序更新表中的行,其中新行值取决于前一行的更新值(请参见问题标题)。你对此有什么意见吗?在Oracle中有一个滞后组函数。查看数据库中是否有与之等效的功能。在Oracle中,有一个滞后组函数。看看你的数据库中是否有与之相当的数据