【问题标题】:PostgreSQL/PostGIS: ST_distance query should only return "nearest" resultPostgreSQL/PostGIS:ST_distance 查询应该只返回“最近”的结果
【发布时间】:2020-07-03 22:14:01
【问题描述】:

我想查询表 A 中每个点 (id) 到表 B 中每个多边形 (id) 的距离。对于距离计算,我使用 ST_Distance。但是,ST_Distance(显然)返回到每个多边形的距离。但我只需要每个点的“最接近”结果。到目前为止,我尝试了以下查询,它返回了正确的结果,但(当然)只针对一个点。

SELECT polygons.id, points.id, ST_Distance(points.geom, polygons.geom) 
FROM table_A AS points, table_B AS polygons 
ORDER BY st_distance ASC LIMIT 1

结果应该是这样的:

polygon_id | point_id | min(distance)
-------------------------------------
1234       |   876    |   54.32
...        |   ...    |    ...
-------------------------------------

你有什么提示吗?非常感谢。

更新 1

WITH CTE AS
       (SELECT polygons.id as poly_id, points.id as point_id, 
        ST_Distance(points.geom, polygons.geom) as thedistance , 
        row_number() OVER
              (PARTITION BY points.id ORDER BY ST_Distance(points.geom, polygons.geom)) 
    FROM 
        table_A AS points
    INNER JOIN table_B AS polygons
    ON ST_DWithin(points.geom, polygons.geom, 100)) SELECT * FROM CTE WHERE row_number = 1

运行上述查询(3h 24m)后返回空结果。但是,应该有结果。会不会是括号有问题?

更新 2

SRID 为 4326 (WGS84),多边形为 OSM 构建多边形,点为同一城市中的任意点。

【问题讨论】:

    标签: postgresql postgis


    【解决方案1】:

    您可以使用window 函数和CTE。像这样的:

    WITH CTE AS
       (select polygons.id as poly_id, points.id as point_id, 
        ST_Distance(points.geom, polygons.geom) as thedistance , 
        row_number() OVER
              (PARTITION BY points.id ORDER by ST_Distance(points.geom, polygons.geom) ) 
    FROM 
     table_A AS points, table_B AS polygons )
     select poly_id, point_id, thedistance from CTE where row_number = 1
    

    但是,如果您有很多积分,这可能会很慢。如果您大致知道点与多边形之间的距离,则可以通过在使用索引的连接中使用 st_dwithin 来加快速度。只需设置距离参数,以便捕捉每个点:

    WITH CTE AS
       (select polygons.id as poly_id, points.id as point_id, 
        ST_Distance(points.geom, polygons.geom) as thedistance , 
        row_number() OVER
              (PARTITION BY points.id ORDER by ST_Distance(points.geom, polygons.geom) ) 
    FROM 
        table_A AS points
    INNER JOINT table_B AS polygons
    ON st_Dwithin(points.geom, polygons.geom, 5000 )) -- assumes you have a metres projection, limit to 5KM
    select * from CTE where row_number = 1
    

    确保您的两个 GEOM 列上都有 GIST 索引

    【讨论】:

    • 非常感谢您的回复。我目前正在运行您提出的查询,我希望它在明天之前完成。我会告诉你的。
    • 查询在 3.5 小时后完成,但没有结果。我不得不稍微修改一下您的查询。我在最终选择语句之前添加了一个右括号,请参阅上面的更新 1。
    • 是的 - 看起来像是括号的错字,抱歉。会修复它。你能发布一些样本记录吗?另外,您使用的是什么 SRID?可能是你的距离太窄,你什么都找不到……
    • 感谢您的回答。我正在使用 4326 WGS84。我猜是度数。我用一个单点 id 尝试过一次,我认为 DWithin 显示了正确的结果。也许我可以排除内部联接? EDIT 样本数据很难提供。基本上,我正在查看 OSM 构建多边形和到任意点(某些城市)的距离。
    • st_dwithin 的要点是它使用索引,所以应该快得多。但是,对于以度为单位的 SRID,这没有多大意义。请尝试第一个查询...
    猜你喜欢
    • 1970-01-01
    • 2022-07-25
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    相关资源
    最近更新 更多