Diferença entre duas camadas no PostGIS


8

Qual é a maneira correta de calcular a diferença entre duas camadas? Eu tentei usar a seguinte abordagem:

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

Mas na saída, perco as geometrias da rivercamada que não cruzam nenhuma geometria lakes. Parece que a junção esquerda não funciona conforme o esperado.

Atualmente, estou usando outra abordagem, mas não tenho certeza se isso está correto:

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) 

Respostas:


11

Apenas faça o seguinte:

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

reverter

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 isso que existe o COALESCE. Eu prefiro manter a semântica do PostGIS do jeito que são. É consistente com a tecnologia aceita pelo banco de dados relacional e, se fizermos consessões para isso, precisamos fazer isso para todas as funções e, em seguida, os resultados serão imprevisíveis.


Não acho que a stackexchange esteja levando minhas edições. O que eu quis dizer foi COALESCE (ST_Diferença (river.geom, lakes.geom), river.geom) Como river_geom ... rio LEFT JOIN lagos. Mas esperamos que você entenda a questão #
LR1234567

6

O problema aqui não é a junção esquerda, está funcionando como esperado. Mas quando a consulta chega a um rio que não se cruza com um lago, ela alimenta a função ST_Difference com NULL como o segundo argumento que parece retornar nulo.

/ Nicklas


2
Eu acho que retornar NULL é a coisa certa a fazer? Como Paulo mencionou - deve se comportar como btrim etc. Se você quisesse retornar o primeiro argumento quando não houvesse correspondência, usaria COALESCE. A junção não retornaria o lago se a diferença estivesse vazia. alterar esse comportamento quebraria muito código - pois as pessoas que dependem desse comportamento precisariam se preocupar com a ordem dos argumentos e assim por diante. por exemplo, COALESCE (ST_Diferença ..., river.geom, the_world); COALESCE permite aplicar um número indefinido de argumentos e é a maneira padrão como programadores de banco de dados lidam com NULL.
LR1234567

Sim, você está certo, é claro :-) Você nunca pensou nisso antes, por que a junção deve retornar um valor indefinido em vez de vazio ou nada quando não há correspondência.
Nicklas Avén
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.