cálculo da área percentual de interseção na cláusula where

15

Eu tenho uma tabela de polígonos (grupos de blocos de censo) no postgres. Quero marcar cada grupo de blocos com a cidade (outra tabela de polígonos) em que reside principalmente. Isso é possível? Estou pensando que precisaria essencialmente criar algo como:

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  

mas essa consulta está demorando uma eternidade (eu tenho cerca de 5.000 grupos de blocos e 375 cidades ...). Alguma sugestão sobre como fazer essa consulta funcionar, se estiver incorreta ou mais rápida, se estiver correta?

eirvin
fonte
Parece que você deseja marcar os grupos de blocos com base na sobreposição máxima? Se sim, veja esta resposta . Se suas 'cidades' também são geografias do Censo (MCDs ou Locais, por exemplo), provavelmente não há necessidade de calcular a porcentagem de sobreposição.
Dbaston 28/05

Respostas:

23

A maneira como você está fazendo isso funcionará, mas levará muito tempo, pois o postgis está tentando criar a geometria da interseção de todas as combinações "grupo de blocos versus cidade", mesmo quando elas nem se tocam.

Adicione outra verificação de condição à sua cláusula WHERE para verificar se as duas geometrias interceptam e coloque-a antes da existente:

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

No SQL, se você tiver uma lista de condições na cláusula WHERE, elas serão testadas pela ordem em que foram gravadas. Se um FALSE for retornado em uma das operações anteriores, a consulta simplesmente ignorará a verificação de outras condições, pois o resultado será sempre FALSE.

Além disso, verifique se você possui índices espaciais em blockgroups.wkb_geometry e towns.wkb_geometry.

Alexandre Neto
fonte
1
A adição ST_Intersectsé o caminho certo a seguir, mas o planejador pode ou não executar as condições na ordem em que foram escritas. Veja os documentos do Postgres para detalhes sobre isso. ST_Intersectse ST_Intersectiontenho o mesmo custo na minha instalação (100), portanto, para ser sincero, não tenho certeza do que o planejador está fazendo, mas sempre parece fazer a coisa certa aqui.
Dbaston 28/05
Ahh ... eu assumi que as condições seriam verificadas como em outros idiomas. Mas acho que isso dá ao planejador outra opção.
Alexandre Neto
10

Acrescentando a resposta muito útil de Alexandre, se algumas de suas unidades censitárias abrangerem três de suas cidades (e, portanto, você não pode garantir mais de 50% de quedas em qualquer cidade), faça o seguinte:

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;

Isso basicamente protege contra a seguinte situação - na qual as áreas em azul desapareceriam: insira a descrição da imagem aqui

RobinL
fonte
1
Eu absolutamente adoro quando a primeira questão que encontro com uma resposta SO é resolvida pela próxima resposta. Saúde, @RobinL!
Wfgeo