Mettre à jour la ligne de base de données avec des points qui tombent dans des polygones

10

J'ai une base de données PostGIS / Postgresql qui contient deux tables. L'une avec des géométries ponctuelles et l'autre qui représente les frontières des pays sous forme de polygones. Je voudrais ajouter le nom du pays que chaque point recoupe à chaque ligne de ma table de points. Peut-être comme une grande requête de mise à jour. Je pense que cela est possible en utilisant directement SQL mais je ne sais pas par où commencer. Tout conseil sur ce sujet serait grandement apprécié...

AdamEstrada
la source

Réponses:

9

Une autre option, sans avoir besoin de la fonction

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

Je soupçonne (même si je n'ai pas testé) que ce sera plus rapide que d'utiliser une fonction imbriquée comme dans votre exemple.

Ma sortie de course à pied explique (j'espère que votre look est similaire). Si vous avez plus de résultats Seq Scan, alors c'est quelque chose à regarder, peut-être que les index ne sont pas assez bien configurés.

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
la source
Impressionnant! Cela semble également être beaucoup plus rapide. Merci!
AdamEstrada
4

OK ... J'ai fait un peu de piratage et j'ai constaté qu'une fonction SQL m'a permis de faire la plupart du chemin. Quelqu'un a-t-il des idées pour amener ça au pont?

 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
la source