PostGIS'te kesişmeyen özellikleri seçin


41

Bu bana bu kadar basit bir soru gibi görünüyor (ve muhtemelen de öyle) ancak bana cevap veren bir örnek bulamıyorum. PostGIS'i kullanarak, sadece çokgenlerin dışına düşen noktaları seçmek istiyorum . Sonuçta bu, görebildiğim kadarıyla ST_Iersters'ın tersi.

Örnek: Bir taxlot katmanına ve bir adres noktası katmanına sahibim. ST_Iersters'ı kullanmam gerektiğini düşünüyorum, ama bunun tersini yapmasını nasıl söyleyebilirim? Aşağıdaki kodun önüne bir NOT ifadesi eklemeyi düşünmüştüm , ancak bu işe yaramadı.

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);

Ben, aynı düşünce süreci vardı da diğerleri gibi hile yapacağını DEĞİL düşündüm nerede durum
Luffydude

Yanıtlar:


41

“Kesişmeme” ile çalışmamasının nedeni, sadece geometrileri çiftler halinde karşılaştırmanızdır; ayrıklıkla aynı sorun olacaktır. Her ev noktası bir parselle kesişse bile bazı parselleri ayırır.

underdark'in önerisinde bu sorun yok. Ayrıca, endeksleri daha etkin kullanabilecek başka bir numara daha var:

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;

Fikir onlara st_intersects ile katılmak ve parsel kimliğinin bulunmadığı satırları almaktır.

Burada ihtiyaç duyulan endeksler uzamsal bir dizin ve parsellerdeki giddeki bir dizindir (parsel tablosundaki kimliğin de buna gideceğini varsayarsak).


2
Çok teşekkür ederim! Nicklas, ST_Disjoint’in doğru sonuçları vermeyeceği kesin olarak doğru ST_Disjoint tüm özellikleri döndürür, çünkü işaret ettiği gibi, her bir nokta tablodaki bazı parsel çokgenleriyle bağlantısızdır , bu kod pasajı bana umduğum sonuçları verirdi.
RyanDalton,

Bu sorgu, bu gis.stackexchange.com/a/136177/6052 ile aynı olarak planlanacaktır, bu nedenle tamamen tercih ettiğiniz bir stil meselesidir. =) Bu alışveriş cevapları için.
Evan Carroll

14

ST_Disjoint arıyor olabilirsiniz

ST_Disjoint - Geometriler "uzamsal olarak kesişmiyorsa" TRUE döndürür - birlikte bir boşluk paylaşmazlarsa.


2
ST_Disjoint bunu yaparken, uzaysal dizinleri kullanmaz. Bir loooooong boyunca bekleyeceksiniz
nickves 12:15

9

Özel bir fonksiyon yoksa:

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

Burada kullanıyoruz NOT EXISTSve CREATE 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

ST_Disjoint nasıl? - Geometriler "uzamsal olarak kesişmezse" - TRUE, birlikte bir boşluk paylaşmazlarsa TRUE döndürür.


4
whoops - cevap vermeden önce bir sayfa yenileme yapmanız gerekiyor :-)
Ian Turton

1

Bazı durumlarda çok faydalıdır LATERAL JOIN, kullanımı çok hızlı olabilir.

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

ST_Intersects'ten önce basitçe NOT'u kullanmak hileyi yapmaz:

Bu, # 62 mahallesinde olmayan tüm adresleri alır:

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'

Geom sütunlarının sırasına dikkat edin - ilk önce çokgenler, ikinci, ST_Intersects kullanımından ters çevrilen puanlar.

Çabuk ve basit! Bir süredir bunun doğru şekilde nasıl yapıldığını merak ediyordum!


Ayrıca "NOT ST_Within" için de çalıştı. Sorgu, NOT ST_Within ve dış birleşim kullanarak ~ 30.0 saniyede tamamlandı ve ardından sağ tarafta Null kontrolü yapıldı, bu nedenle herhangi bir performans isabeti görünmüyor. Teşekkürler!
Nate Wanner

@NateWanner bilmek güzel! Bunun ne kadar kolay ve hızlı olduğuna inanamıyorum !!!
DPSSpatial

Bu aslında oldukça kötü bir fikir çünkü kartezyen ürünü alıyorsunuz
Evan Carroll

@EvanCarroll bu ne anlama geliyor?
DPSSpatial

Eğer sadece 1 denver.adres almadıysanız, eşleşmeyen her denver.neighborhood için bir tane alıyorsunuz demektir.
Evan Carroll 17

-1

Bu en hızlı çözüm olmayabilir ... Ama genelde sadece diğer tablonun tüm özelliklerine katılarak hile yapıyorum.

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);

Not_in_here tablo o kadar karmaşık değilse hoş ve çabuk .


Bu asla çabuk olmaz. Sadece not_in_here'nin karmaşık olması durumunda olacağı kadar kayıtsız değil . ;)
Evan Carroll 17
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.