假设我在postgresql数据库中有一个表,其中包含列:time,speed
现在我添加了一个列“distance
”,我希望通过类似的方式插入距离值:
row[time+1].distance = row[time].distance + row[time+1].speed
这是更新表格的最快方法吗?
更新
我想尝试类似的事情:
d = 0.0
for row in select time,speed from my_table loop
d = d + row.speed
update my_table set distance = d where time = row.time
end loop
这是最好的方法吗?如何让这个代码段运行?
答案 0 :(得分:1)
所以,我做了一张桌子:
create table whatever ( time_c int4, speed int4, distance int8);
并插入了一些行:
insert into whatever (time_c, speed) select i, random() * 100 from generate_series(1,10) i;
这给了我这个数据:
$ select * from whatever;
time_c | speed | distance
--------+-------+----------
1 | 53 | [null]
2 | 17 | [null]
3 | 53 | [null]
4 | 46 | [null]
5 | 31 | [null]
6 | 18 | [null]
7 | 42 | [null]
8 | 15 | [null]
9 | 1 | [null]
10 | 51 | [null]
(10 rows)
然后,我使用DO
命令:
do $$
DECLARE
tmp_cur cursor for SELECT * FROM whatever ORDER BY time_c for UPDATE;
temprec record;
total_distance INT4 := 0;
BEGIN
open tmp_cur;
LOOP
fetch tmp_cur INTO temprec;
EXIT WHEN NOT FOUND;
total_distance := total_distance + temprec.speed;
UPDATE whatever SET distance = total_distance WHERE CURRENT OF tmp_cur;
END LOOP;
END;
$$;
这就是全部:
$ select * from whatever;
time_c | speed | distance
--------+-------+----------
1 | 53 | 53
2 | 17 | 70
3 | 53 | 123
4 | 46 | 169
5 | 31 | 200
6 | 18 | 218
7 | 42 | 260
8 | 15 | 275
9 | 1 | 276
10 | 51 | 327
(10 rows)
答案 1 :(得分:1)
无需循环甚至无需存储此数据。显然你想要一个“速度”列的“运行总和”,可以使用窗口函数轻松完成:
(从Depesz的回答中无耻地窃取样本数据)
create table whatever
(
time_c int4,
speed int4,
distance int8
);
insert into whatever (time_c, speed)
values
( 1,53),
( 2,17),
( 3,53),
( 4,46),
( 5,31),
( 6,18),
( 7,42),
( 8,15),
( 9, 1),
(10,51);
select time_c,
speed,
sum(speed) over (order by time_c) as distance
from whatever
order by time_c;
time_c | speed | distance -------+-------+--------- 1 | 53 | 53 2 | 17 | 70 3 | 53 | 123 4 | 46 | 169 5 | 31 | 200 6 | 18 | 218 7 | 42 | 260 8 | 15 | 275 9 | 1 | 276 10 | 51 | 327
如果您确实想要存储可以轻松计算的数据,可以使用单个更新语句来执行此操作:
with derived_data as (
select time_c,
speed,
sum(speed) over (order by time_c) as distance
from whatever
)
update whatever
set distance = dd.distance
from derived_data dd
where dd.time_c = whatever.time_c;
此更新假定time_c
是表中的唯一属性。
SQLFiddle示例:http://sqlfiddle.com/#!12/16332/2
答案 2 :(得分:0)
看到你的评论,最简单的方法是将row.distance表示为前一行的速度之和*。
选择看起来像这样(使用它来运行一些检查):
select t1.id, sum (t1.speed * time_diff) as distance
from table t1 join table t2 on t1.time >= t2.time
group by t1.id
如果您对此感到满意,请将其用作更新声明中的子选择:
update table ... from (...) sub where sub.id = table.id
(旁白:请注意,您的距离公式不考虑加速度。)