PostgreSQL / PostGIS: запрос ST_distance должен возвращать только «ближайший» результат - PullRequest
0 голосов
/ 23 марта 2020

Я хотел бы запросить расстояние для каждой точки (id) в таблице A до каждого многоугольника (id) в таблице B. Для расчета расстояния я использую 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
...        |   ...    |    ...
-------------------------------------

Do у вас есть какие-нибудь намеки? Большое спасибо.

ОБНОВЛЕНИЕ 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

После выполнения вышеуказанного запроса (3 ч. 24 м.) Был возвращен пустой результат. Однако должен быть результат. Возможно ли, что есть проблема с круглыми скобками?

ОБНОВЛЕНИЕ 2

SRID - 4326 (WGS84), а многоугольники - это многоугольники построения OSM, а точки - произвольные точки. в том же городе.

1 Ответ

0 голосов
/ 23 марта 2020

Вы можете использовать функцию окна и 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

Убедитесь, что у вас есть индексы GIST в обоих столбцах GEOM

...