Perbedaan antara dua lapisan di PostGIS

8

Apa cara yang tepat untuk menghitung perbedaan antara dua lapisan? Saya mencoba menggunakan pendekatan berikut:

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

Tetapi dalam output, saya kehilangan geometri dari riverlayer yang tidak memotong geometri lakes. Sepertinya gabung kiri tidak berfungsi seperti yang diharapkan.

Saat ini, saya menggunakan pendekatan lain, tetapi saya tidak yakin ini benar:

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
sumber

Jawaban:

11

Lakukan ini:

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

balik

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

Itulah tujuan keberadaan COALESCE. Saya lebih suka menjaga semantik PostGIS apa adanya. Ini konsisten dengan teknologi DB relasional yang diterima dan jika kita membuat konsesi untuk ini, kita perlu melakukannya untuk semua fungsi dan hasilnya tidak dapat diprediksi.

LR1234567
sumber
Saya tidak berpikir stackexchange mengambil suntingan saya. Yang ingin saya katakan adalah COALESCE (ST_Difference (river.geom, lakes.geom), river.geom) Sebagai river_geom ... river LEFT JOIN lake. Tapi semoga Anda mendapatkan ide
LR1234567
6

Masalahnya di sini bukan join kiri, yang berfungsi seperti yang diharapkan. Tetapi ketika query sampai ke sungai yang tidak bersinggungan dengan danau itu akan memberi makan fungsi ST_Difference dengan NULL sebagai argumen kedua yang tampaknya mengembalikan nol.

/ Nicklas

Nicklas Avén
sumber
2
Saya pikir mengembalikan NULL adalah hal yang benar untuk dilakukan? Seperti yang disebutkan Paul - itu harus berperilaku seperti btrim dll. Jika Anda ingin mengembalikan argumen pertama ketika tidak cocok Anda akan menggunakan COALESCE. Bergabung tidak akan mengembalikan danau jika perbedaannya kosong. mengubah perilaku ini akan mematahkan banyak kode - karena orang yang mengandalkan perilaku ini kemudian harus khawatir tentang urutan argumen dan sebagainya. misalnya COALESCE (ST_Difference ..., river.geom, the_world); COALESCE memungkinkan Anda untuk menerapkan jumlah argumen yang tidak terbatas dan merupakan cara standar yang digunakan pemrogram database dengan NULL.
LR1234567
Ya, Anda benar, tentu saja :-) Belum pernah memikirkannya sebelumnya, mengapa bergabung harus mengembalikan nilai yang tidak ditentukan alih-alih kosong atau tidak sama sekali ketika tidak ada kecocokan.
Nicklas Avén