Postgresql
我可以根據前一個值是否是我想要的來迭代一個值嗎?
假設我在 PostgreSQL 9.4 中有這個表:
CREATE TABLE trajs ( id serial NOT NULL PRIMARY KEY, obj_id integer, traj_id integer, geom geometry, t timestamp without time zone );
以下是數據的樣子:
obj_id, traj_id, geom, t 1 1 point '2016-04-29 09:35:00' 1 1 point '2016-04-29 09:40:00' 1 1 point '2016-04-29 09:55:00' 2 1 point '2016-04-29 09:35:00' 2 1 point '2016-04-29 09:42:00' 2 1 point '2016-04-29 09:50:00' 3 1 point '2016-04-29 09:35:00' 3 1 point '2016-04-29 09:41:00' 3 1 point '2016-04-29 09:43:00'
對於每個“obj_id”,我可以根據前一個之間的“t”距離迭代“traj_id”嗎?
一個例子:對於每 6 分鐘的差異(第一個對象之間的時間,如該表中的第 3 列和第 1 列),這應該是一個新的
traj_id
(+1) - 並重新啟動一個新的obj_id
. 結果應該是這樣的:obj_id, traj_id, geom, t 1 1 point '2016-04-29 09:35:00' 1 1 point '2016-04-29 09:40:00' 1 2 point '2016-04-29 09:55:00' 2 1 point '2016-04-29 09:35:00' 2 2 point '2016-04-29 09:42:00' 2 3 point '2016-04-29 09:50:00' 3 1 point '2016-04-29 09:35:00' 3 2 point '2016-04-29 09:41:00' 3 2 point '2016-04-29 09:43:00'
我開始這樣做,但我的解決方案不起作用。而且我看不到每次滿足條件時它如何迭代。
update trajs t set traj_id = traj_id+1 where t.t > (select ant.t + interval '6 minutes' from trajs ant where t.obj_id=ant.obj_id);
如何解決這個問題?
對於 Postgres 9.4+:
UPDATE trajs t SET traj_id = upd.traj_id FROM ( SELECT id, 1 + count(*) FILTER (WHERE t >= t0 + interval '6 min') OVER (PARTITION BY obj_id ORDER BY t) AS traj_id FROM ( SELECT id, obj_id, t, lag(t) OVER (PARTITION BY obj_id ORDER BY t) AS t0 FROM trajs ) sub ) upd WHERE t.id = upd.id AND t.traj_id IS DISTINCT FROM upd.traj_id;
traj_id
僅目前一行早於 6 分鐘或更早時才增加- 完全符合要求。關於我為優化性能而添加的最後一個條件(最後一段):
我制定它的方式,它也適用於第一行的角落情況
obj_id
,其中lag()
返回NULL
。關於
FILTER
我結合第二個視窗函式的聚合: