Atualizar linha do banco de dados com pontos que se enquadram nos polígonos

10

Eu tenho um banco de dados PostGIS / Postgresql que possui duas tabelas. Uma com geometrias de pontos e a outra que representa os limites do país como polígonos. Gostaria de adicionar o nome do país com o qual cada ponto cruza com cada linha da minha tabela de pontos. Talvez como uma grande consulta de atualização. Eu acho que isso é possível usando SQL direto, mas não sei por onde começar. Qualquer conselho sobre isso seria muito apreciado...

AdamEstrada
fonte

Respostas:

9

Outra opção, sem precisar da função

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

Eu suspeito (embora não tenha testado) que isso será mais rápido do que usar uma função aninhada como no seu exemplo.

Minha saída da execução explica (espero que pareça semelhante). Se você obteve mais resultados de verificação Seq, é algo para se olhar, talvez os índices não estejam configurados corretamente.

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)"
Kelso
fonte
Impressionante! Isso parece ser muito mais rápido também. Obrigado!
AdamEstrada
4

OK ... Eu fiz um pouco de hacking e descobri que uma FUNÇÃO SQL me leva a maior parte do caminho até lá. Alguém tem alguma idéia de levar isso para a ponte?

 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
fonte