Выберите точечные объекты, используя пространственный запрос

У меня есть две таблицы postgres, объекты с одним полигоном и объекты с двумя точками, имеющие одинаковую проекцию. Что я хочу сделать, это выбрать только точки, которые содержатся в большом многоугольнике и не содержатся в маленьких многоугольниках, как показано на рисунке ниже, используя пространственный запрос.

Я пытаюсь сделать с помощью запроса ниже, чтобы select все точки, которые не пересекаются / не содержатся в малом многоугольнике (kind=1), а затем вернуть те точки из выбранных объектов, которые содержатся в большом многоугольнике (kind=2). Результатом запроса является 0 rows,

select 
      *
 from 
    (
     select p.geom as point_geom,sp.geom as polygon_geom
     from polygons sp, points p
     where st_disjoint(sp.polygon_geom,p.point_geom) and sp.kind = 1
    ) as subquery
 where st_contains(subquery.scale_geom,subquery.pois_geom) and subquery.kind = 2;

kind столбец в приведенном выше запросе используется для различения этих полигонов, где kind = 1 представляет собой небольшой многоугольник и kind = 2 большой многоугольник. Кроме того, оба многоугольника перекрываются, что означает, что точки содержатся в маленьком многоугольнике, а также в большом многоугольнике.

Обновить

После выполнения этого запроса:

SELECT DISTINCT p.geom as point_geom FROM points p JOIN polygons poly1 ON ST_Disjoint(p.geom, poly1.geom) JOIN polygons poly2 ON ST_Intersects(p.geom, poly2.geom) WHERE poly1.kind = 1 AND poly2.kind = 2 ;

Некоторые результаты не были приемлемы, как:

Обведенные точки должны быть только в виде 1, но они выбраны.

2 ответа

Решение

Если я вас правильно понимаю, у вас есть два ортогональных условия:

  1. Все точки, которые не пересекаются с kind = 1 многоугольники
  2. Все точки, которые пересекаются с kind = 2 многоугольники

и вам нужно его пересечение. Двойное соединение должно сделать:

SELECT DISTINCT p.geom as point_geom
FROM points p 
     JOIN polygons poly1 ON ST_Disjoint(p.geom, poly1.geom)
     JOIN polygons poly2 ON ST_Intersects(p.geom, poly2.geom)
WHERE 
     poly1.kind = 1 AND poly2.kind = 2
;

должен дать ожидаемый результат. DISTINCT необходимо, только если точка потенциально содержится в нескольких полигонах. Не забудьте поставить индексы на polygons.geom, points.geom, а также polygons.kind, потому что иначе это будет ужасно медленно (EXPLAIN показывает две вложенные петли).

SELECT p.geom AS point_geom, big.geom AS polygon_geom
FROM points p 
JOIN polygons big ON ST_Intersects(big.geom, p.geom) AND big.kind = 1
JOIN polygons small ON (NOT ST_Intersects(small.geom, p.geom)) AND small.kind = 2;

Этот запрос выглядит примерно так: "выбрать все точки, которые пересекают большие многоугольники, но исключить все точки, которые пересекаются с маленьким многоугольником".

Вы должны избегать использования ST_Disjoint() потому что он не использует индексы.

Другие вопросы по тегам