Расчет процента площади пересечения в где пункт

15

У меня есть таблица полигонов (групп блоков переписи) в postgres. Я хочу пометить каждую группу блоков городом (еще одной таблицей полигонов), в котором он находится в основном. Это возможно? Я думаю, мне нужно по сути создать что-то вроде:

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  

но этот запрос занимает вечность (у меня около 5000 групп блоков и 375 городов ...). Любые предложения о том, как заставить этот запрос работать вообще, если он неправильный, или быстрее, если он правильный?

eirvin
источник
Похоже, вы хотите пометить группы блоков на основе максимального перекрытия? Если так, посмотрите этот ответ . Если ваши «города» также являются географическими районами переписи (скажем, MCD или Places), то, вероятно, нет необходимости рассчитывать процент перекрытия.
dbaston

Ответы:

23

То, как вы это делаете, будет работать, но это займет слишком много времени, так как Postgis пытается создать геометрию пересечения каждой комбинации «блок-группа против города», даже если они даже не касаются.

Добавьте еще одну проверку условия в ваше предложение WHERE, чтобы проверить, пересекаются ли две геометрии, и поместите ее перед существующей:

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

В SQL, если у вас есть список условий в предложении WHERE, они проверяются в порядке их написания. Если FALSE возвращается в одной из ранних операций, запрос просто пропустит проверку остальных условий, поскольку результатом всегда будет FALSE.

Также убедитесь, что у вас есть пространственные индексы для blockgroups.wkb_geometry и towns.wkb_geometry.

Александр Нето
источник
1
Добавление ST_Intersects- правильный путь, но планировщик может выполнять или не выполнять условия в том порядке, в котором они написаны. См. Документацию Postgres для подробностей об этом. ST_Intersectsи ST_Intersectionимеют одинаковую стоимость на мою установку (100), поэтому, если честно, я не уверен, что делает планировщик, но здесь, кажется, всегда поступают правильно.
dbaston
Ааа ... Я предполагал, что условия будут проверены, как на других языках. Но я думаю, это даст планировщику еще один вариант.
Александр Нето
10

В дополнение к очень полезному ответу Александра, если некоторые из ваших переписных единиц могут охватывать три ваших города (и, следовательно, вы не можете гарантировать более 50% падений в любом городе), вы можете сделать это:

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;

Это в основном защищает от следующей ситуации - в которой исчезают синие области: введите описание изображения здесь

RobinL
источник
1
Я абсолютно обожаю это, когда самая первая проблема, с которой я сталкиваюсь с ответом SO, будет решена с помощью следующего ответа. Ура, @RobinL!
wfgeo