calcolo dell'area percentuale di intersezione nella clausola where


15

Ho una tabella di poligoni (gruppi di blocchi di censimento) in postgres. Voglio taggare ogni gruppo di blocchi con la città (un'altra tabella poligonale) in cui risiede principalmente. È possibile? Sto pensando che dovrei essenzialmente creare qualcosa del tipo:

select b.*,t.name  
from blockgroups b, towns t  
where (st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) > .5  

ma questa query sta impiegando un'eternità (ho circa 5.000 gruppi di blocchi e 375 città ...). Qualche suggerimento su come far funzionare questa query o se è errata o più veloce se è corretta?


Sembra che tu voglia taggare i gruppi di blocchi in base alla massima sovrapposizione? In tal caso, vedi questa risposta . Se le tue "città" sono anche aree geografiche del censimento (MCD o Luoghi, diciamo), probabilmente non è necessario calcolare la percentuale di sovrapposizione.
dbaston,

Risposte:


23

Il modo in cui lo farai funzionerà ma ci vorrà troppo tempo, dal momento che Postgis sta cercando di creare la geometria dell'intersezione di ogni combinazione "blockgroup vs town", anche quando non si toccano nemmeno.

Aggiungi un altro controllo delle condizioni alla tua clausola WHERE per verificare se le due geometrie si intercettano e mettile prima di quella esistente:

select b.*,t.name
from blockgroups b, towns t
where st_intersects(b.wkb_geometry, t.wkb_geometry) and    
    (st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) > .5

In SQL se si dispone di un elenco di condizioni nella clausola WHERE, vengono testati dall'ordine in cui sono stati scritti. Se un FALSO viene restituito in una delle prime operazioni, la query salterà semplicemente il controllo delle altre condizioni, poiché il risultato sarà sempre FALSO.

Inoltre, assicurati di avere indici spaziali su blockgroups.wkb_geometry e towns.wkb_geometry.


1
L'aggiunta ST_Intersectsè il modo giusto per andare qui, ma il pianificatore può o meno eseguire le condizioni nell'ordine in cui sono scritte. Vedi i documenti di Postgres per i dettagli al riguardo. ST_Intersectse ST_Intersectionho lo stesso costo sulla mia installazione (100), quindi ad essere sincero non sono sicuro di cosa stia facendo il planner, ma qui sembra sempre fare la cosa giusta.
dbaston,

Ahh ... Pensavo che le condizioni sarebbero state controllate come in altre lingue. Ma suppongo che dia al pianificatore un'altra opzione.
Alexandre Neto,

10

Aggiungendo alla risposta molto utile di Alexandre, se alcune delle tue unità di censimento possono estendersi su tre delle tue città (e quindi non puoi garantire che oltre il 50% cada in qualsiasi città) puoi farlo:

select distinct on (b.id)
b.*,t.name,
(st_area(st_intersection(b.wkb_geometry, t.wkb_geometry))/st_area(b.wkb_geometry)) as proportion
from blockgroups b, towns t
where st_intersects(b.wkb_geometry, t.wkb_geometry) 
order by b.id, proportion desc;

Questo in pratica protegge dalla seguente situazione - in cui le aree in blu scomparirebbero: inserisci qui la descrizione dell'immagine


1
Lo adoro assolutamente quando il primo problema che riscontro con una risposta SO è risolto dalla risposta successiva. Saluti, @RobinL!
wfgeo,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.