Выберите точечные объекты, используя пространственный запрос
У меня есть две таблицы 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 ответа
Если я вас правильно понимаю, у вас есть два ортогональных условия:
- Все точки, которые не пересекаются с
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
;
должен дать ожидаемый результат. 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()
потому что он не использует индексы.