Diferencia entre dos capas en PostGIS

8

¿Cuál es la forma correcta de calcular la diferencia entre dos capas? Traté de usar el siguiente enfoque:

SELECT ST_Difference(river.geom, lakes.geom) 
FROM river LEFT JOIN lakes ON ST_Intersects(river.geom, lakes.geom) 

Pero en la salida, pierdo las geometrías de la rivercapa que no se cruzan con ninguna geometría lakes. Parece que la combinación izquierda no funciona como se esperaba.

Actualmente, estoy usando otro enfoque, pero no estoy seguro de que sea correcto:

SELECT ST_Difference(river.geom, lakes.geom) 
FROM river JOIN lakes ON ST_Intersects(river.geom, lakes.geom) 
UNION 
SELECT river.geom 
FROM river JOIN lakes ON NOT ST_Intersects(river.geom, lakes.geom) 
drnextgis
fuente

Respuestas:

11

Solo haz esto:

SELECT COALESCE(ST_Difference(river.geom, lakes.geom), river.geom) As river_geom 
FROM river LEFT JOIN lakes ON ST_Intersects(river.geom, lakes.geom);

contrarrestar

SELECT COALESCE(ST_Difference(river.geom, lakes.geom), lakes.geom) As lake_geom 
FROM lakes LEFT JOIN river ON ST_Intersects(river.geom, lakes.geom);

Para eso existe COALESCE. Prefiero mantener la semántica de PostGIS como están. Es coherente con la tecnología de base de datos relacional aceptada y si hacemos concesiones para esto, tenemos que hacerlo para todas las funciones y los resultados serán impredecibles.

LR1234567
fuente
No creo que stackexchange esté tomando mis ediciones. Lo que quise decir fue COALESCE (ST_Difference (river.geom, lakes.geom), river.geom) Como river_geom ... river IZQUIERDA UNIRSE a los lagos. Pero espero que se te
ocurra
6

El problema aquí no es la unión izquierda, que funciona como se esperaba. Pero cuando la consulta llega a un río que no se cruza con un lago, alimentará la función ST_Difference con NULL como el segundo argumento que parece devolver nulo.

/ Nicklas

Nicklas Avén
fuente
2
¿Creo que devolver NULL es lo correcto? Como mencionó Paul, debería comportarse como btrim, etc. Si quisiera devolver el primer argumento cuando no hay coincidencias, usaría COALESCE. La unión no devolvería el lago si la diferencia estuviera vacía. cambiar este comportamiento rompería mucho código, ya que las personas que dependen de este comportamiento tendrían que preocuparse por el orden de los argumentos, etc. por ejemplo, COALESCE (ST_Difference ..., river.geom, the_world); COALESCE le permite aplicar un número indefinido de argumentos y es la forma estándar en que los programadores de bases de datos tratan con NULL.
LR1234567
Sí, tiene razón, por supuesto :-) No lo he pensado antes, por qué la combinación debe devolver un valor indefinido en lugar de un vacío o nada cuando no hay coincidencia.
Nicklas Avén