在一系列 GPS 数据中寻找最近的经过点

Finding the closest passing points in a series of GPS data

我有一个具有以下架构的 table:

                Table "public.gps_log"
          Column           |            Type             
---------------------------+-----------------------------
 id                        | integer                     
 logged_at                 | timestamp without time zone 
 lonlat                    | geography(Point,4326)       

另一个具有以下架构:

               Table "public.waypoint"
          Column           |            Type             
---------------------------+-----------------------------
 id                        | integer                     
 lonlat                    | geography(Point,4326)       
 range                     | numeric

gps_log 包含来自 GPS 的每分钟位置报告,waypoint 包含一组 waypoints 及其位置。

我有以下查询:

SELECT gps_log.id as id1, waypoint.id as id2, ST_Distance(gps_log.lonlat, waypoint.lonlat) as dist
  FROM gps_log, waypoint
  WHERE ST_DWithin(gps_log.lonlat, waypoint.lonlat, waypoint.range)
  ORDER BY id1;

return结果如下:

  id1  | id2  |      dist      
-------+------+----------------
  4499 | 1118 | 2580.557160943  <- first and closest dist in this cluster of id2=1118
  4500 | 1118 | 2580.557160943
  4501 | 1119 | 3861.038787463  <- etc. ...
  4502 | 1119 | 3861.038787463
  4503 | 1118 |  885.481236082  <-
  4504 | 1118 |  885.481236082
  4505 | 1119 | 2114.289192152  <-
  4506 | 1119 | 2114.289192152
  4507 | 1118 | 3209.147139384
  4508 | 1118 | 3209.147139384
  4510 | 1118 | 2194.494307877  <-
  4511 | 1118 | 2194.494307877
  4514 | 1118 | 2253.163728865
  4515 | 1117 | 3155.907772254  <-
  4518 | 1117 | 3875.930499045
  4519 | 1118 | 3834.344459575  <-
  4522 | 1117 | 2025.333877603  <-
  4523 | 1117 | 2025.333877603
  4603 | 1116 | 1075.801799628
  4604 | 1116 | 1075.801799628
  4607 | 1116 |  663.907042351
  4608 | 1116 |  663.907042351
  4611 | 1116 |  319.142003353  <-
  4612 | 1116 |  319.142003353
  4614 | 1116 |   535.03813233
  4615 | 1116 |   535.03813233
  4630 | 1132 | 2134.348193208
  4631 | 1181 |  2165.19731156  <-
  4784 | 1134 |  337.398349813  <-
  4785 | 1134 |  337.398349813
  4788 | 1135 | 1388.859874755  <-
  4789 | 1135 | 1388.859874755

我最终希望查询到return最近通过每个航点的GPS位置报告,并且一个航点可以多次通过。

上面的箭头代表我想return作为查询结果的记录——基本上每次有一个新的路点ID集群,离路点最近距离的位置报告是returned.

现在,我的解决方案是 运行 上面的查询,然后在代码中处理结果以循环遍历数组并找到正确的值。

这是 "gaps-and-islands" 问题的变体。您可以使用不同的行号来标识组。然后,您可以使用 DISTINCT ON:

提取具有最小距离的行
WITH d as (
      SELECT gps_log.id as id1, w.id as id2, ST_Distance(gl.lonlat, w.lonlat) as dist
      FROM gps_log gl JOIN
           waypoint w
           ON ST_DWithin(ol.lonlat, w.lonlat, w.range)
     )
SELECT DISTINCT ON (id2, grp) d.*
FROM (SELECT d.*,
             (ROW_NUMBER() OVER (ORDER BY id1) - 
              ROW_NUMBER() OVER (PARTITION BY id2 ORDER BY id1)
             ) as grp
      FROM d
     ) d
ORDER BY id2, grp, dist;

理解为什么行号的差异起作用是相当棘手的。我建议您 运行 子查询生成两个行数值。然后您可以看到差异如何定义您想要的组。