Seleccione las características que NO se intersecan en PostGIS

35

Esto me parece una pregunta tan simple (y probablemente lo sea) pero parece que no puedo encontrar un ejemplo que me dé la respuesta. Con PostGIS, solo quiero seleccionar puntos que queden fuera de los polígonos. En última instancia, esto es lo inverso de los ST_Intersects, por lo que puedo ver.

Ejemplo: Tengo una capa de taxlot y una capa de punto de dirección. Supongo que debería usar los ST_Intersects, pero ¿cómo le digo que haga la selección inversa? Pensé que tal vez agregar una declaración NOT delante del código a continuación, pero eso no funcionó.

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);
    
pregunta RyanDalton 16.12.2010 - 22:41

8 respuestas

36

La razón por la que no funciona con "no intersecta" es que solo se comparan las geometrías en pares; Habrá el mismo problema con la separación. Cada punto del hogar separará algunas parcelas incluso si se cruza una parcela.

la sugerencia de underdark no tiene ese problema. También hay otro truco que probablemente hará un uso más efectivo de los índices:

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;

La idea es unirlos con st_intersects y obtener las filas donde no está presente la identificación de la parcela.

Los índices que se necesitan aquí son un índice espacial y un índice de gid en parcelas (asumiendo que la id en la tabla de parcelas también se llama gid).

    
respondido por el Nicklas Avén 17.12.2010 - 00:02
14

Puede que estés buscando ST_Disjoint

  

ST_Disjoint - Devuelve VERDADERO si las Geometrías no "espacialmente   intersect ", si no comparten ningún espacio juntos.

    
respondido por el Jason Scheirer 16.12.2010 - 23:01
9

En caso de que no haya una función especializada:

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
    
respondido por el underdark 16.12.2010 - 22:57
4

Aquí usamos NOT EXISTS y 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)
  );
    
respondido por el Carl Sena Afenu 20.02.2015 - 15:22
2

¿Qué hay de ST_Disjoint? - Devuelve VERDADERO si las Geometrías no se "intersectan espacialmente" - si no comparten ningún espacio juntos.

    
respondido por el Ian Turton 16.12.2010 - 23:07
1

En algunos casos es muy útil el uso LATERAL JOIN, puede ser muy rápido. Debería verse como

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;
    
respondido por el Jelen 21.08.2017 - 11:05
0

Simplemente usando NO antes de que ST_Intersects haga el truco:

Esto obtiene todas las direcciones que no están dentro del vecindario # 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'

Tenga en cuenta el orden de las columnas geom: polígonos primero, puntos segundo, que se invierte del uso habitual de ST_Intersects.

¡Rápido y simple! ¡Me he estado preguntando cómo hacer esto correctamente por un tiempo!

    
respondido por el DPSSpatial 20.01.2017 - 22:54
-1

Puede que esta no sea la solución más rápida ... Pero generalmente solo hago trampa uniéndome a todas las características de la otra tabla.

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

Agradable y rápido si la tabla not_in_here no es tan compleja.

    
respondido por el Jamie Popkin 12.01.2016 - 04:47

Lea otras preguntas en las etiquetas