Postgresql postgres-为T2中的每一行选择时间戳之前T1中最新的一行
我看了好几个问题,但没有找到答案。因此,如果能提供类似解决方案的答案/链接,我将不胜感激。 我有两张桌子:交通工具和活动。每辆车都有多个GPS位置——假设玩具示例中有4辆车,有11行GPS ping。但是玩具测试只有两个项目 例如车辆(每行有唯一的Postgresql postgres-为T2中的每一行选择时间戳之前T1中最新的一行,postgresql,gps,postgis,postgresql-9.3,Postgresql,Gps,Postgis,Postgresql 9.3,我看了好几个问题,但没有找到答案。因此,如果能提供类似解决方案的答案/链接,我将不胜感激。 我有两张桌子:交通工具和活动。每辆车都有多个GPS位置——假设玩具示例中有4辆车,有11行GPS ping。但是玩具测试只有两个项目 例如车辆(每行有唯一的gid,每辆车有vehicle\u id,还有时间戳date\u time和位置geom): 事件(唯一的gid、时间戳t\u日期和位置geom): 目的是了解每次活动时的情况,哪些车辆更接近,然后优化活动车辆的分配。 因此,我想加入这些表格,以便为每
gid
,每辆车有vehicle\u id
,还有时间戳date\u time
和位置geom
):
事件(唯一的gid
、时间戳t\u日期
和位置geom
):
目的是了解每次活动时的情况,哪些车辆更接近,然后优化活动车辆的分配。
因此,我想加入这些表格,以便为每个事件获取最多4行(作为车辆数量),每个车辆的最后已知位置在事件前120分钟的时间段内,直到事件时间,按两者之间的距离排序。我想把它们放在同一张表中,这样我就可以按时间、地点、事件类型等进行比较
现在我被困在这里了。我知道如何找到特定时间段内(比如19:10之前)车辆的最新记录。但这不是我需要的,因为它在19:10切断了车辆表。但对于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 ;
我得到了错误的日期,并且每辆车只有一次(我猜是因为不同的),但我需要每个事件一次,以及适当的最后位置(因此在本例中,两个事件两次)
理想情况下,我还希望下一步为每辆车设置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
我看不到任何确保DISTINCT ON(c.gid,v.vehicle\u id)
将拾取具有最小d\t
的记录的东西。你确定它会吗?它确实有效,并选择了最后一个dt_v
,谢谢@Clodoaldo Neto。不过@Dario:说不定可以做WHERE v.date_time@Lizardie它将始终选择最大值。当由
发出正确的
订单时,这是一个
上的独特功能。检查手册。@Clodoaldo Neto tnx,是的,它将选择最大值dt_v
,从而选择最小值d_t
(即从事件到最后一个已知位置的时间距离),以下是链接
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)
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