เลือกคุณสมบัติที่ไม่ตัดกันใน PostGIS


41

ดูเหมือนว่าฉันจะชอบคำถามง่ายๆ (และอาจเป็น) แต่ฉันก็ไม่สามารถหาตัวอย่างที่ให้คำตอบได้ ใช้ PostGIS ฉันแค่ต้องการเลือกจุดที่อยู่นอกรูปหลายเหลี่ยม ท้ายที่สุดนี่คือสิ่งที่ตรงกันข้ามของ ST_Intersects เท่าที่ฉันจะเห็น

ตัวอย่าง: ฉันมีเลเยอร์ภาษีและชั้นที่อยู่ ฉันคิดว่าฉันควรใช้ ST_Intersects แต่ฉันจะบอกให้ทำการเลือกแบบย้อนกลับได้อย่างไร ฉันคิดว่าอาจเพิ่มคำสั่งNOTด้านหน้าโค้ดด้านล่าง แต่นั่นไม่ได้ผล

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

ฉันมีกระบวนการคิดที่เหมือนกันคิดว่าการทำเช่นนี้จะไม่เหมือนคนอื่นที่มีเงื่อนไข
Luffydude

คำตอบ:


41

เหตุผลที่ใช้ไม่ได้กับ "ไม่ตัดกัน" คือคุณเปรียบเทียบรูปทรงเรขาคณิตเป็นคู่เท่านั้น จะมีปัญหาเดียวกันกับ disjoint housepoint ทุกคนจะแยกจากกันบางส่วนแม้ว่ามันจะตัดหนึ่งพัสดุ

ข้อเสนอแนะของ underdark ไม่มีปัญหานั้น นอกจากนี้ยังมีเคล็ดลับอีกอย่างที่อาจทำให้การใช้ดัชนีมีประสิทธิภาพมากขึ้น:

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;

แนวคิดคือการเข้าร่วมกับ st_intersects และรับแถวที่ไม่มีรหัสพัสดุ

ดัชนีที่ต้องการในที่นี้คือดัชนีเชิงพื้นที่และดัชนีของ gid ในพัสดุ (สมมติว่า id ในตารางพัสดุเรียกว่า gid ด้วย)


2
ขอบคุณมาก! Nicklas นั้นถูกต้องอย่างแน่นอนว่า ST_Disjoint จะไม่ให้ผลลัพธ์ที่ถูกต้อง ST_Disjoint ผลตอบแทนคุณสมบัติทั้งหมดเพราะในขณะที่เขาชี้ให้เห็นจุดแต่ละจุดจะไม่ปะติดปะต่อกับบางรูปหลายเหลี่ยมพัสดุในตารางในขณะที่ข้อมูลโค้ดนี้ให้ฉันผลที่ฉันหวัง
RyanDalton

ข้อความค้นหานี้จะได้รับการวางแผนเหมือนกับgis.stackexchange.com/a/136177/6052นี้ดังนั้นจึงเป็นเรื่องของสไตล์ที่คุณต้องการอย่างหมดจด =) สำหรับคำตอบการช็อปปิ้งเหล่านั้น
Evan Carroll

14

คุณอาจกำลังมองหาST_Disjoint

ST_Disjoint - ส่งคืน TRUE หากรูปทรงเรขาคณิตไม่ได้ "ปริภูมิเชิงปริภูมิ" - หากพวกเขาไม่แชร์พื้นที่ใด ๆ ด้วยกัน


2
ในขณะที่ ST_Disjoint ทำเช่นนั้น แต่ไม่ได้ใช้ดัชนีเชิงพื้นที่ คุณกำลังจะรอเวลา loooooong
nickves

9

ในกรณีที่ไม่มีฟังก์ชั่นพิเศษ:

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

ที่นี่เราใช้NOT EXISTSและ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 ล่ะ? - ส่งคืน TRUE หากรูปทรงเรขาคณิตไม่ได้ "ปริภูมิเชิงปริภูมิ" - หากพวกเขาไม่แชร์พื้นที่ใด ๆ ด้วยกัน


4
อ๊ะ - ต้องทำการรีเฟรชหน้าก่อนตอบ :-)
Ian Turton

1

ในบางกรณีการใช้ LATERAL JOIN นั้นมีประโยชน์มากมันอาจเร็วมาก

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

เพียงใช้ NOT ก่อนที่ ST_Intersects จะทำเคล็ดลับ:

สิ่งนี้ได้รับที่อยู่ทั้งหมดที่ไม่อยู่ในละแวกใกล้เคียง # 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'

หมายเหตุลำดับของคอลัมน์ geom - รูปหลายเหลี่ยมอันดับแรกคือจุดที่สองซึ่งย้อนกลับจากการใช้งานปกติของ ST_Intersects

ง่ายและรวดเร็ว! เคยสงสัยว่าจะทำอย่างถูกต้องได้สักพัก!


ใช้ได้กับ "NOT ST_ ภายใน" ด้วย ข้อความค้นหาของฉันเสร็จสมบูรณ์ใน ~ 30.0 วินาทีสำหรับทั้ง NOT ST_ ภายในและใช้การรวมภายนอกจากนั้นตรวจสอบ Null ทางด้านขวาดังนั้นดูเหมือนจะไม่มีประสิทธิภาพใด ๆ ขอบคุณ!
Nate Wanner

@NateWanner รู้ดี! ฉันไม่อยากจะเชื่อเลยว่ามันง่ายและรวดเร็วเพียงใด !!!
DPSSpatial

อันที่จริงมันเป็นความคิดที่ไม่ดีนักเพราะคุณได้รับผลิตภัณฑ์คาร์ทีเซียน
Evan Carroll

@EvanCarroll นั่นหมายความว่าอย่างไร
DPSSpatial

หมายความว่าหากคุณไม่ได้รับเพียง 1 denver.address คุณจะได้รับหนึ่ง denver.neighbor
Evan Carroll

-1

นี่อาจไม่ใช่วิธีที่เร็วที่สุด ... แต่ฉันมักจะโกงด้วยการเข้าร่วมคุณสมบัติทั้งหมดของตารางอื่น

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นั้นไม่ซับซ้อน


ที่ไม่เคยมีความสุข มันก็ไม่ได้เป็นความสุขอย่างที่มันจะเป็นถ้าnot_in_มีความซับซ้อน ;)
Evan Carroll
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.