选择在PostGIS中不相交的要素


41

在我看来,这似乎是一个简单的问题(可能是),但我似乎找不到能给我答案的例子。使用PostGIS,我只想选择不在多边形范围内的点。就我所知,这最终是ST_Intersects的逆函数。

示例:我有一个taxlot层和一个地址点层。我假设我应该使用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

Answers:


41

它不适用于“不相交”的原因是,您只能成对比较几何;脱节将存在相同的问题。每个房屋点即使与一个地块相交也将不相交。

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连接起来,并获得不存在宗地ID的行。

这里需要的索引是空间索引和宗地中gid的索引(假设宗地表中的id也称为gid)。


2
非常感谢你!Nicklas完全正确,因为ST_Disjoint将不会产生正确的结果。正如他指出的那样,ST_Disjoint返回所有要素,因为每个点都与表中的某些宗地多边形不相交,而此代码段给出了我想要的结果。
RyanDalton 2010年

该查询的计划与此gis.stackexchange.com/a/136177/6052相同,因此,这纯粹是您喜欢的样式问题。=)对于那些购物答案。
埃文·卡罗尔


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 EXISTSand 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
糟糕-在回答之前需要刷新页面:-)
伊恩·特顿

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

在ST_Intersects之前简单地使用NOT即可达到目的:

这将获取不在#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_Within”工作。对于NOT ST_Within和使用外部联接,我的查询均在约30.0秒内完成,然后在右侧检查Null,因此似乎对性能没有任何影响。谢谢!
Nate Wanner

@NateWanner很高兴认识!我不敢相信那是多么容易和快捷!
DPSSpatial

这实际上是一个坏主意,因为您要获得笛卡尔积
Evan Carroll

@EvanCarroll是什么意思?
DPSSpatial

这意味着,如果您不仅获得1个denver.address,还为每个不匹配的denver.neighborhood获得一个。
埃文·卡罗尔

-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_here很复杂,它不会变得那么卑鄙。;)
埃文·卡罗尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.