postgres - select T1 中的最新行就在 T2 中每一行的时间戳之前
postgres - select latest row in T1 just before timestamp for each row in T2
我检查了多个问题,但没有找到答案。因此,对于类似的解决方案,我将不胜感激 answer/link。
我有两个 table:车辆和事件。每辆车都有多个 GPS 位置 - 假设玩具示例中有 4 辆车,有 11 行 GPS ping。但说玩具测试只有 2 个事件。
例如车辆(每一行都有唯一的gid
,每辆车有vehicle_id
,还有时间戳date_time
和位置geom
):
SELECT gid, vehicle_id, date_time, geom FROM test_v vehicles ORDER BY 2,3,1;
gid | vehicle_id | date_time | geom
---------+------------+---------------------+----------------------------------------------------
1257854 | 742 | 2009-06-06 19:02:01 | 01010000208A7D0000667CC002A7262741A444A87995324041
1258089 | 742 | 2009-06-06 19:03:29 | 01010000208A7D00007ABCA45AD22227415A5ADEB5662E4041
1258842 | 742 | 2009-06-06 19:07:23 | 01010000208A7D000083D5151C7414274196D0D21AE7284041
1259213 | 742 | 2009-06-06 19:09:11 | 01010000208A7D000054160E1FE4052741D6E2E74CD2284041
1257939 | 3055 | 2009-06-06 19:02:31 | 01010000208A7D0000327D6277FAF426418EA975ECB6504041
1258898 | 3055 | 2009-06-06 19:07:41 | 01010000208A7D000003519FB5D5F6264166B1B943C3514041
1259313 | 3425 | 2009-06-06 19:09:35 | 01010000208A7D0000418D23C296442741FCFCEF0069394041
1258008 | 3426 | 2009-06-06 19:02:56 | 01010000208A7D000011958634824027414D5D3823A43C4041
1258307 | 3426 | 2009-06-06 19:04:37 | 01010000208A7D0000C8017753AB38274175E727CBA43A4041
1258744 | 3426 | 2009-06-06 19:06:56 | 01010000208A7D00005F9811D7903A274145135F0589384041
1259018 | 3426 | 2009-06-06 19:08:13 | 01010000208A7D0000546B478B323A2741F4CB8DB6AD374041
(11 rows)
事件(唯一 gid
、时间戳 t_date
和位置 geom
):
SELECT gid, t_date, geom FROM test_c events;
gid | t_date | geom
-------+---------------------+----------------------------------------------------
13009 | 2009-06-06 19:04:31 | 01010000208A7D000034F06A423F18274123DF6756B8194041
13021 | 2009-06-06 19:08:53 | 01010000208A7D0000D093E2A470FE26413E935C3A5E304041
想法是了解每个事件发生时的情况,哪些车辆更近,然后优化车辆分配到事件。
所以我想加入这些 tables 以便我为每个事件获得最多 4 行(作为车辆数量)以及每辆车在 120 分钟之前的时间段内的最后已知位置事件和直到事件时间,按两者之间的距离排序。我希望它们在同一个 table 中,这样我就可以按时间、地点、事件类型等对它们进行比较。
现在我被困在这里了。我知道如何找到特定时间段内车辆的最新记录(比如 19:10)。但这不是我需要的,因为它在时间 19:10 切断了 table 的车辆。但是对于 gid= 13009
时间为 19:04:31
的事件,因此可能包含一个晚于事件的位置。我想要的是事件发生时的最新位置,每个事件显然都不同。
我试过这个:
SELECT DISTINCT ON (1)
v.vehicle_id
, row_number() OVER() as gid
, st_distance(v.geom, c.geom)::float4 as distance_m
, c.gid as c_gid
, v.gid as v_gid
, c.t_date as dt_c
, v.date_time as dt_v
, (c.t_date - v.date_time) as d_t
FROM (SELECT * FROM test_c ) as c
, (SELECT * FROM test_v ORDER BY date_time DESC ) v
WHERE date_time >= (c.t_date - '120 minute' :: INTERVAL) AND date_time <= (c.t_date + '0 minute' :: INTERVAL)
ORDER BY 1, 7 DESC , 5, 6 , c.geom <-> v.geom ASC ;
这是我得到的:
vehicle_id | gid | distance_m | c_gid | v_gid | dt_c | dt_v | d_t
------------+-----+------------+-------+---------+---------------------+---------------------+----------
742 | 3 | 4748.6 | 13021 | 1258842 | 2009-06-06 19:08:53 | 2009-06-06 19:07:23 | 00:01:30
3055 | 2 | 17125.8 | 13021 | 1258898 | 2009-06-06 19:08:53 | 2009-06-06 19:07:41 | 00:01:12
3426 | 1 | 8515.65 | 13021 | 1259018 | 2009-06-06 19:08:53 | 2009-06-06 19:08:13 | 00:00:40
(3 rows)
我得到的日期不正确,而且每辆车只出现一次(我猜是因为 DISTINCT
),但我需要它们在每个事件中出现一次并具有适当的最后位置(因此在此示例中,2 次事件为 2 次)。
理想情况下,我还希望下一步为每辆车设置 3 个最新位置,但也许那是以后的事。
我是这样理解的:
select *
from (
select distinct on (c.gid, v.vehicle_id)
v.vehicle_id
, row_number() over(order by v.gid) as gid
, st_distance(v.geom, c.geom)::float4 as distance_m
, c.gid as c_gid
, v.gid as v_gid
, c.t_date as dt_c
, v.date_time as dt_v
, (c.t_date - v.date_time) as d_t
from
test_c c
inner join
test_v v on
date_time between c.t_date - '120 minute' :: interval and c.t_date
order by c.gid, v.vehicle_id, v.date_time desc
) s
order by c_gid, distance_m
;
vehicle_id | gid | distance_m | c_gid | v_gid | dt_c | dt_v | d_t
------------+-----+------------+-------+---------+---------------------+---------------------+----------
742 | 8 | 10674.9 | 13009 | 1258089 | 2009-06-06 19:04:31 | 2009-06-06 19:03:29 | 00:01:02
3426 | 5 | 18607.5 | 13009 | 1258008 | 2009-06-06 19:04:31 | 2009-06-06 19:02:56 | 00:01:35
3055 | 4 | 28516.8 | 13009 | 1257939 | 2009-06-06 19:04:31 | 2009-06-06 19:02:31 | 00:02:00
742 | 11 | 4748.6 | 13021 | 1258842 | 2009-06-06 19:08:53 | 2009-06-06 19:07:23 | 00:01:30
3426 | 13 | 8515.65 | 13021 | 1259018 | 2009-06-06 19:08:53 | 2009-06-06 19:08:13 | 00:00:40
3055 | 12 | 17125.8 | 13021 | 1258898 | 2009-06-06 19:08:53 | 2009-06-06 19:07:41 | 00:01:12
我检查了多个问题,但没有找到答案。因此,对于类似的解决方案,我将不胜感激 answer/link。 我有两个 table:车辆和事件。每辆车都有多个 GPS 位置 - 假设玩具示例中有 4 辆车,有 11 行 GPS ping。但说玩具测试只有 2 个事件。
例如车辆(每一行都有唯一的gid
,每辆车有vehicle_id
,还有时间戳date_time
和位置geom
):
SELECT gid, vehicle_id, date_time, geom FROM test_v vehicles ORDER BY 2,3,1;
gid | vehicle_id | date_time | geom
---------+------------+---------------------+----------------------------------------------------
1257854 | 742 | 2009-06-06 19:02:01 | 01010000208A7D0000667CC002A7262741A444A87995324041
1258089 | 742 | 2009-06-06 19:03:29 | 01010000208A7D00007ABCA45AD22227415A5ADEB5662E4041
1258842 | 742 | 2009-06-06 19:07:23 | 01010000208A7D000083D5151C7414274196D0D21AE7284041
1259213 | 742 | 2009-06-06 19:09:11 | 01010000208A7D000054160E1FE4052741D6E2E74CD2284041
1257939 | 3055 | 2009-06-06 19:02:31 | 01010000208A7D0000327D6277FAF426418EA975ECB6504041
1258898 | 3055 | 2009-06-06 19:07:41 | 01010000208A7D000003519FB5D5F6264166B1B943C3514041
1259313 | 3425 | 2009-06-06 19:09:35 | 01010000208A7D0000418D23C296442741FCFCEF0069394041
1258008 | 3426 | 2009-06-06 19:02:56 | 01010000208A7D000011958634824027414D5D3823A43C4041
1258307 | 3426 | 2009-06-06 19:04:37 | 01010000208A7D0000C8017753AB38274175E727CBA43A4041
1258744 | 3426 | 2009-06-06 19:06:56 | 01010000208A7D00005F9811D7903A274145135F0589384041
1259018 | 3426 | 2009-06-06 19:08:13 | 01010000208A7D0000546B478B323A2741F4CB8DB6AD374041
(11 rows)
事件(唯一 gid
、时间戳 t_date
和位置 geom
):
SELECT gid, t_date, geom FROM test_c events;
gid | t_date | geom
-------+---------------------+----------------------------------------------------
13009 | 2009-06-06 19:04:31 | 01010000208A7D000034F06A423F18274123DF6756B8194041
13021 | 2009-06-06 19:08:53 | 01010000208A7D0000D093E2A470FE26413E935C3A5E304041
想法是了解每个事件发生时的情况,哪些车辆更近,然后优化车辆分配到事件。
所以我想加入这些 tables 以便我为每个事件获得最多 4 行(作为车辆数量)以及每辆车在 120 分钟之前的时间段内的最后已知位置事件和直到事件时间,按两者之间的距离排序。我希望它们在同一个 table 中,这样我就可以按时间、地点、事件类型等对它们进行比较。
现在我被困在这里了。我知道如何找到特定时间段内车辆的最新记录(比如 19:10)。但这不是我需要的,因为它在时间 19:10 切断了 table 的车辆。但是对于 gid= 13009
时间为 19:04:31
的事件,因此可能包含一个晚于事件的位置。我想要的是事件发生时的最新位置,每个事件显然都不同。
我试过这个:
SELECT DISTINCT ON (1)
v.vehicle_id
, row_number() OVER() as gid
, st_distance(v.geom, c.geom)::float4 as distance_m
, c.gid as c_gid
, v.gid as v_gid
, c.t_date as dt_c
, v.date_time as dt_v
, (c.t_date - v.date_time) as d_t
FROM (SELECT * FROM test_c ) as c
, (SELECT * FROM test_v ORDER BY date_time DESC ) v
WHERE date_time >= (c.t_date - '120 minute' :: INTERVAL) AND date_time <= (c.t_date + '0 minute' :: INTERVAL)
ORDER BY 1, 7 DESC , 5, 6 , c.geom <-> v.geom ASC ;
这是我得到的:
vehicle_id | gid | distance_m | c_gid | v_gid | dt_c | dt_v | d_t
------------+-----+------------+-------+---------+---------------------+---------------------+----------
742 | 3 | 4748.6 | 13021 | 1258842 | 2009-06-06 19:08:53 | 2009-06-06 19:07:23 | 00:01:30
3055 | 2 | 17125.8 | 13021 | 1258898 | 2009-06-06 19:08:53 | 2009-06-06 19:07:41 | 00:01:12
3426 | 1 | 8515.65 | 13021 | 1259018 | 2009-06-06 19:08:53 | 2009-06-06 19:08:13 | 00:00:40
(3 rows)
我得到的日期不正确,而且每辆车只出现一次(我猜是因为 DISTINCT
),但我需要它们在每个事件中出现一次并具有适当的最后位置(因此在此示例中,2 次事件为 2 次)。
理想情况下,我还希望下一步为每辆车设置 3 个最新位置,但也许那是以后的事。
我是这样理解的:
select *
from (
select distinct on (c.gid, v.vehicle_id)
v.vehicle_id
, row_number() over(order by v.gid) as gid
, st_distance(v.geom, c.geom)::float4 as distance_m
, c.gid as c_gid
, v.gid as v_gid
, c.t_date as dt_c
, v.date_time as dt_v
, (c.t_date - v.date_time) as d_t
from
test_c c
inner join
test_v v on
date_time between c.t_date - '120 minute' :: interval and c.t_date
order by c.gid, v.vehicle_id, v.date_time desc
) s
order by c_gid, distance_m
;
vehicle_id | gid | distance_m | c_gid | v_gid | dt_c | dt_v | d_t
------------+-----+------------+-------+---------+---------------------+---------------------+----------
742 | 8 | 10674.9 | 13009 | 1258089 | 2009-06-06 19:04:31 | 2009-06-06 19:03:29 | 00:01:02
3426 | 5 | 18607.5 | 13009 | 1258008 | 2009-06-06 19:04:31 | 2009-06-06 19:02:56 | 00:01:35
3055 | 4 | 28516.8 | 13009 | 1257939 | 2009-06-06 19:04:31 | 2009-06-06 19:02:31 | 00:02:00
742 | 11 | 4748.6 | 13021 | 1258842 | 2009-06-06 19:08:53 | 2009-06-06 19:07:23 | 00:01:30
3426 | 13 | 8515.65 | 13021 | 1259018 | 2009-06-06 19:08:53 | 2009-06-06 19:08:13 | 00:00:40
3055 | 12 | 17125.8 | 13021 | 1258898 | 2009-06-06 19:08:53 | 2009-06-06 19:07:41 | 00:01:12