Chọn các tính năng KHÔNG giao nhau trong PostGIS


41

Điều này đối với tôi giống như một câu hỏi đơn giản như vậy (và có lẽ là vậy) nhưng dường như tôi không thể tìm thấy một ví dụ cho tôi câu trả lời. Sử dụng PostGIS, tôi chỉ muốn chọn các điểm nằm ngoài đa giác. Cuối cùng, đây là nghịch đảo của ST_Intersects, theo như tôi có thể thấy.

Ví dụ: Tôi có một lớp taxlot và một lớp điểm địa chỉ. Tôi giả sử tôi nên sử dụng ST_Intersects, nhưng làm cách nào để bảo nó thực hiện lựa chọn ngược? Tôi nghĩ có thể thêm một câu lệnh KHÔNG vào trước đoạn mã bên dưới, nhưng điều đó không hiệu quả.

CREATE table t_intersect AS
SELECT 
  hp.gid, 
  hp.st_address, 
  hp.city, 
  hp.st_num,
  hp.the_geom
FROM 
  public.parcel as par,
  public.housepoints as hp
WHERE 
  ST_Intersects(hp.the_geom,par.the_geom);

Tôi đã có quá trình suy nghĩ tương tự, nghĩ rằng KHÔNG cũng sẽ thực hiện mánh khóe như bất kỳ điều kiện nào khác
Luffydude

Câu trả lời:


41

Lý do nó không hoạt động với "không giao nhau" là vì bạn chỉ so sánh hình học theo cặp; sẽ có cùng một vấn đề với sự rời rạc. Mỗi housepoint sẽ phân biệt một số bưu kiện ngay cả khi nó giao nhau một bưu kiện.

đề nghị của underdark không có vấn đề đó. Ngoài ra còn có một mẹo khác có thể sẽ giúp sử dụng chỉ mục hiệu quả hơn:

CREATE TABLE t_intersect AS
SELECT 
  hp.gid, 
  hp.st_address, 
  hp.city, 
  hp.st_num,
  hp.the_geom
FROM 
  public.housepoints AS hp LEFT JOIN
  public.parcel AS par ON
  ST_Intersects(hp.the_geom,par.the_geom)
WHERE par.gid IS NULL;

Ý tưởng là tham gia cùng họ với st_intersects và nhận các hàng không có id bưu kiện.

Các chỉ mục cần thiết ở đây là một chỉ mục không gian và một chỉ số về gid tính theo bưu kiện (giả sử rằng id trong bảng bưu kiện cũng được gọi là gid).


2
Cảm ơn rât nhiều! Nicklas hoàn toàn chính xác rằng ST_Disjoint sẽ không tạo ra kết quả chính xác. ST_Disjoint trả về tất cả các tính năng bởi vì, như ông đã chỉ ra, mỗi điểm bị tách rời với một số đa giác bưu kiện trong bảng, trong khi đoạn mã này cho tôi kết quả mà tôi hy vọng.
RyanDalton

Truy vấn này sẽ được lên kế hoạch giống như truy vấn này gis.stackexchange.com/a/136177/6052 vì vậy đây hoàn toàn là vấn đề về phong cách mà bạn thích. =) Đối với những câu trả lời mua sắm.
Evan Carroll

14

Bạn có thể đang tìm kiếm ST_Disjoint

ST_Disjoint - Trả về ĐÚNG nếu Hình học không "giao nhau về mặt không gian" - nếu chúng không chia sẻ bất kỳ khoảng trống nào với nhau.


2
Mặc dù ST_Disjoint thực hiện điều đó, tuy nhiên nó không sử dụng các chỉ mục không gian. Bạn sẽ đợi một thời gian loooooong
biệt danh

9

Trong trường hợp không có chức năng chuyên biệt:

CREATE table t_intersect AS
SELECT 
  hp.gid, 
  hp.st_address, 
  hp.city, 
  hp.st_num,
  hp.the_geom
FROM
  public.housepoints as hp
WHERE
  hp.gid NOT IN 
  (
    SELECT 
      h.gid
    FROM 
      public.parcel as p,
      public.housepoints as h
    WHERE 
      ST_Intersects(h.the_geom,p.the_geom)
  ) AS foo

5

Ở đây chúng tôi sử dụng NOT EXISTSCREATE TABLE AS SELECT(CTAS)

CREATE table t_intersect
AS
  SELECT 
    hp.gid,
    hp.st_address,
    hp.city, hp.st_num,
    hp.the_geom
  FROM public.housepoints AS hp
  WHERE NOT EXISTS (
    SELECT 1
    FROM public.parcel AS par 
    WHERE ST_Intersects(hp.the_geom,par.the_geom)
  );

3

Làm thế nào về ST_Disjoint? - Trả về ĐÚNG nếu Hình học không "giao nhau về mặt không gian" - nếu chúng không chia sẻ bất kỳ khoảng trống nào với nhau.


4
Rất tiếc - cần làm mới trang trước khi trả lời :-)
Ian Turton

1

Trong một số trường hợp rất hữu ích, hãy sử dụng LATITH THAM GIA, nó có thể rất nhanh Nó trông giống như

SELECT * FROM houses h
LEFT JOIN LATERAL (
   SELECT True t FROM parcels p
   WHERE ST_Intersects(p.geom, h.geom)
   LIMIT 1
) p ON True
WHERE p.t IS NULL;

1

Đơn giản chỉ cần sử dụng KHÔNG trước khi ST_Intersects thực hiện thủ thuật:

Điều này nhận được tất cả các địa chỉ không nằm trong khu phố # 62:

select 
a.*
from denver.neighborhoods as n
join denver.addresses as a on not ST_Intersects(n.geom, a.geom)
where n.nbhd_id = '62'

Lưu ý thứ tự của các cột geom - đa giác đầu tiên, điểm thứ hai, được đảo ngược so với cách sử dụng thông thường của ST_Intersects.

Nhanh chóng và đơn giản! Đã tự hỏi làm thế nào để làm điều này một cách chính xác trong một thời gian!


Cũng làm việc cho "KHÔNG ST_Within". Truy vấn của tôi đã hoàn thành trong ~ 30,0 giây cho cả KHÔNG ST_Within và sử dụng nối ngoài sau đó kiểm tra Null ở phía bên phải, do đó dường như không có bất kỳ hiệu suất nào. Cảm ơn!
Nate Wanner

@NateWanner tốt để biết! Tôi không thể tin rằng nó dễ dàng và nhanh chóng đến thế !!!
DPSSpatial

Đây thực sự là một ý tưởng khá tồi bởi vì bạn đang nhận được sản phẩm cartesian
Evan Carroll

@EvanCarroll điều đó có nghĩa là gì?
DPSSpatial

Điều đó có nghĩa là nếu bạn không chỉ nhận được 1 denver.address, thì bạn sẽ nhận được một cho mỗi denver.neQU không phù hợp.
Evan Carroll

-1

Đây có thể không phải là giải pháp nhanh nhất ... Nhưng tôi thường chỉ gian lận bằng cách tham gia tất cả các tính năng của bảng khác.

Create table blah as
select
  d.*
from
  data_i_want d,
  (select st_union(geom) geom from not_in_here) n
where
  st_disjoint(d.geom,n.geom);

Đẹp và linh hoạt nếu bảng not_in_here không phức tạp.


Điều đó không bao giờ linh hoạt. Nó sẽ không vui như vậy nếu không_in_here phức tạp. ;)
Evan Carroll
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.