Обновить строку базы данных точками, которые попадают в полигоны

10

У меня есть БД PostGIS / Postgresql, в которой есть две таблицы. Один с точечной геометрией, а другой представляет границы страны в виде многоугольников. Я хотел бы добавить название страны, с которой пересекается каждая точка, к каждой строке в моей таблице точек. Может быть, как один большой запрос на обновление. Я думаю, что это возможно сделать с помощью прямого SQL, но я не знаю, с чего начать. Любой совет по этому вопросу будет принята с благодарностью ...

AdamEstrada
источник

Ответы:

9

Другой вариант, без необходимости функции

update points set country = t1.country from 
(
    select points.oid, countries.name as country from
    countries INNER JOIN points on st_contains(countries.wkb_geometry,points.wkb_geometry)
) t1 
where t1.oid = points.oid

Я подозреваю (хотя я не проверял), что это будет быстрее, чем использование вложенной функции, как в вашем примере.

Мой вывод из бега объяснить (надеюсь, ваша внешность похожа). Если вы получили больше результатов Seq Scan, то на это стоит обратить внимание, возможно, индексы настроены не совсем правильно.

Update on points  (cost=1.18..29.40 rows=121 width=129)"
  ->  Nested Loop  (cost=1.18..29.40 rows=121 width=129)"
        Join Filter: _st_contains(countries.geometry, public.points.geometry)"
        ->  Hash Join  (cost=1.18..2.37 rows=28 width=220)"
              Hash Cond: (public.points.oid = public.points.oid)"
              ->  Seq Scan on points  (cost=0.00..1.08 rows=28 width=114)"
              ->  Hash  (cost=1.08..1.08 rows=28 width=110)"
                    ->  Seq Scan on points  (cost=0.00..1.08 rows=28 width=110)"
        ->  Index Scan using "countries_Idx" on countries  (cost=0.00..0.91 rows=1 width=414)"
              Index Cond: (geometry && public.points.geometry)"
Келсо
источник
Потрясающие! Похоже, это тоже намного быстрее. Спасибо!
AdamEstrada
4

Хорошо ... Я немного взломал и обнаружил, что SQL-функция помогает мне в этом. У кого-нибудь есть мысли по поводу переноса этого на мост?

 CREATE OR REPLACE FUNCTION getcountry (
       country_geom geometry
    ) RETURNS TABLE(country text) AS $$
        SELECT b.name as country FROM  
                    geonames d, world_borders b WHERE
                    $1 && b.wkb_geometry 
                    AND intersects($1, b.wkb_geometry) ;
  $$ LANGUAGE SQL;

UPDATE geonames 
    SET country = val
    FROM (SELECT getcountry(point_geom) FROM geonames) AS val
AdamEstrada
источник