banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Rencontres QGIS 2025

L'appel à participation est ouvert jusqu'au 19 janvier 2025!

#1 Mon 24 October 2011 17:12

mcdelay
Participant occasionnel
Lieu: Lille
Date d'inscription: 19 Sep 2005
Messages: 25

Requete spatiale postGIS

Bonjour,

Je démarre juste avec les requêtes spatiales sous postGIS et je cherche à faire une requête spatiale entre 3 couches mais je m'emmêle les pinceaux.

J'ai 3 tables une couche de point (point de collecte), et 2 couches de polygone (zone et batiment). Je cherche a savoir pour un point de collecte, le nombre de bâtiment se trouvant dans la zone la plus proche d'un point de collecte. En gros j'ai 2 requêtes et il faudrait que je les imbrique !

1er : pour connaître le nombre de bâtiment dans une zone


Code:

SELECT COUNT(DISTINCT(bati.ogc_fid)) AS nbreLogement FROM zone LEFT JOIN bati Intersects(bati.the_geom , zone.the_geom)

2ième: pour connaître et sélectionner la zone la plus proche d'un point de collecte


Code:

SELECT zone.ogc_fid, Distance(zone.the_geom ,Pointcollecte.the_geom)   FROM zone, Pointcollecte ORDER BY Distance ASC LIMIT 1

(Peut être faut-il écrire cette dernière autrement ...)

Petite question, quelle est la différence entre utiliser le préfixe ST par exemple ST_Intersect et Intersect ? D'après ce que je comprends, c'est un histoire d'indexation sur le champ the_geom, qu'est ce que cela implique concrêtement ?

Merci !

Hors ligne

 

#2 Mon 24 October 2011 18:02

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1554

Re: Requete spatiale postGIS

mcdelay a écrit:

Bonjour,

Je démarre juste avec les requêtes spatiales sous postGIS et je cherche à faire une requête spatiale entre 3 couches mais je m'emmêle les pinceaux.

J'ai 3 tables une couche de point (point de collecte), et 2 couches de polygone (zone et batiment). Je cherche a savoir pour un point de collecte, le nombre de bâtiment se trouvant dans la zone la plus proche d'un point de collecte. En gros j'ai 2 requêtes et il faudrait que je les imbrique !

1er : pour connaître le nombre de bâtiment dans une zone


Code:

SELECT COUNT(DISTINCT(bati.ogc_fid)) AS nbreLogement FROM zone LEFT JOIN bati Intersects(bati.the_geom , zone.the_geom)

2ième: pour connaître et sélectionner la zone la plus proche d'un point de collecte


Code:

SELECT zone.ogc_fid, Distance(zone.the_geom ,Pointcollecte.the_geom)   FROM zone, Pointcollecte ORDER BY Distance ASC LIMIT 1

(Peut être faut-il écrire cette dernière autrement ...)

Petite question, quelle est la différence entre utiliser le préfixe ST par exemple ST_Intersect et Intersect ? D'après ce que je comprends, c'est un histoire d'indexation sur le champ the_geom, qu'est ce que cela implique concrêtement ?

Merci !


Bonsoir,

Pour faire ceci en une seule requete, il faut utiliser quelques "tricks" de postgresql, PostGIS < 2.0 ne possedant pas encore d'operateur Nearest Neighbors:

Le principe est de choisir en premier les zones les plus proches des points de collecte, puis de regarder les batiments inclus (ou intersectant, suivant votre cas) dans les zones (non testé dans votre cas):


Code:

with plus_proche as (
    select distinct on(z.ogc_fid) ogc_fid, 
    distance(z.the_geom ,pt.the_geom) as d, 
    z.geom as zone_geom
    from zone z, Pointcollecte pt
    where st_dwithin(z.geom, pt.geom, 500)
    order by d
) select pt_ogc_fid, count(b.ogc_fid) as nbrelogement
from bati b
where st_within(b.geom, zone_geom)
group by pt_ogc_fid;

La premiere requete, obtenue avec la clause WITH, tente de lister les zones les plus proches de chaque point et ne garde que le premier candidat => le plus proche.
Pour cela, l'operateur st_dwithin est utilisé avec une distance fixée en dur, c'est la que le bât blesse: il faut connaitre ou estimer la distance max au dela de laquelle aucun point n'est dans une zone.

Ensuite, la deuxieme requete utilise la premiere pour compter le nombre de batiments dans chaque zone la plus proche du point de collecte.

Concernant la difference entre st_ et pas st_, deux choses:
    • L'adoption par Postgis de la norme SQL MM impose de nommer les fonctions st_, pour plus de clarté et les séparer des autres fonctions de la base.
    • Historiquement, dans postgis, l'utilisation des index spatiaux n'etait pas automatique lors de clauses where, mais necessitait d'utiliser l'operateur &&. Lors de la mise en conformité des noms de fonctions, il a ete décidé d'ajouter en plus, dans les fonctions st_*, un appel automatique a l'index, histoire de rendre nos vie plus faciles (smile )

Concretement, si vous faites des selects sans preciser de clause where ou de jointure spatiale, aucune différence entre les deux notations.
Dans l'autre cas: jointures spatiales, alors ne pas utiliser les index, c'est prendre le risque de requetes prenant beaucoup de temps (qd je dis beaucoup, un index spatial peut faire tomber le temps de requete de plusieurs heures a 1s).

Dans votre cas, la creation d'index spatiaux sur chaque colonne geo de vos tables est indispensable.

Nicolas

Dernière modification par Nicolas Ribot (Mon 24 October 2011 21:34)

Hors ligne

 

#3 Mon 24 October 2011 21:38

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1554

Re: Requete spatiale postGIS

Dans une version un peu plus propre:


with plus_proche as (
   select distinct on(pt.ogc_fid) pt.ogc_fid as pt_id,
          z.ogc_fid as zone_id,
          z.the_geom as zone_geom
   from zone z, Pointcollecte pt
   where st_dwithin(z.the_geom, pt.the_geom, 500)
   order by pt.ogc_fid, distance(z.the_geom, pt.the_geom)
) select p.pt_id, p.zone_id, count(b.ogc_fid) as nbrelogement
from bati b, plus_proche p
where st_within(b.the_geom, p.zone_geom)
group by p.pt_id, p.zone_id;

Cela liste, pour chaque point de collecte, la zone la plus proche et le nombre de bâtiments qui s'y trouvent.
La distance arbitraire de 500m doit être ajustée en fonction des données: c'est la distance maximale entre les points de collecte et les zones.

S'il y a beaucoup de points de collecte par rapport au nombre de zones, ça peut être intéressant de calculer dans un premier temps le nombre de bâtiments par zone.

Nicolas

Hors ligne

 

#4 Wed 26 October 2011 15:27

mcdelay
Participant occasionnel
Lieu: Lille
Date d'inscription: 19 Sep 2005
Messages: 25

Re: Requete spatiale postGIS

Nicolas,

Merci beaucoup pour ta réponse ! Ca fonctionne très bien et ça m'a permis de faire ma première requête spatiale complexe ;-)

J'ai utilisé la requête de ton deuxième message et je l'ai réadaptée à mes besoins. Petite question pour que je comprenne bien, le order de la première requête permet de classer les zones par distance et quel est l'élément permettant de ne prendre que la zone la plus proche ppur un point de collecte ?

Merci

Hors ligne

 

#5 Wed 26 October 2011 16:44

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1554

Re: Requete spatiale postGIS

mcdelay a écrit:

Nicolas,

Merci beaucoup pour ta réponse ! Ca fonctionne très bien et ça m'a permis de faire ma première requête spatiale complexe ;-)


Ah cool.

J'ai utilisé la requête de ton deuxième message et je l'ai réadaptée à mes besoins. Petite question pour que je comprenne bien, le order de la première requête permet de classer les zones par distance et quel est l'élément permettant de ne prendre que la zone la plus proche ppur un point de collecte ?

Merci


oui, le premier ordre by permet de classer par distance croissante. Puis le distinct on de la partie select ne garde que le premier record parmi ceux qui partagent le meme pt_ogc_fid.
Ce n'est pas SQL 92, mais c'est une fonction de Postgresql bien pratique. Ca permet d'eliminer des lignes qui partagent un ou plusieurs attributs communs (mais pas tous: ici la distance change a chaque record. Un DISTINCT traditionnel aurait gardé toutes les zones pour chaque point de collecte).

Nico

Dernière modification par Nicolas Ribot (Wed 26 October 2011 16:46)

Hors ligne

 

Pied de page des forums

Powered by FluxBB