#1 Hier 11:10
- ppluvinet
- Participant assidu
- Lieu: VALENCE
- Date d'inscription: 6 Aug 2007
- Messages: 615
UPDATE avec un WITH RECURSIVE
Bonjour,
J'ai une couche de polygones dont certains petits polygones ont un attribut NULL.
J'aimerai affecter à ces petits polygones la valeur d'un des polygones voisins. Comme certains sont entourés eux-mêmes de petits polygones avec des valeurs nulles, je souhaitais utiliser une fonction récursive qui ferait un UPDATE tant qu'il y a des valeurs nulles.
J'ai tenté la rédaction ci-après mais ca ne met à jour qu'une fois les polygones , la récursivité ne fonctionne pas et il reste des polygones avec des valeurs nulles qui ne sont pourtant pas isolés.
N'étant pas à l'aise avec les fonctions récursives, je fais appel à vos compétences
Code:
WITH RECURSIVE b AS ( SELECT * FROM poly WHERE attr is not null ) UPDATE poly a SET attr = b.attr FROM b WHERE a.attr is null AND st_intersects(a.geom,b.geom) ;
Merci d'avance pour vos suggestions,
Dernière modification par ppluvinet (Hier 11:54)
Pascal PLUVINET
Hors ligne
#2 Hier 12:00
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1157
Re: UPDATE avec un WITH RECURSIVE
Salut,
Il serait plus facile je pense d'écrire une fonction pl/psql pour arriver à ce que vous voulez faire.
Cela dit, voilà une idée de requête qui pourrait peut être fonctionner :
Code:
WITH RECURSIVE r(id, geom, attr) AS ( SELECT --partie de base de la requête recursive : on récupére tous les polygones sans attributs ayant un voisin avec attribut a.id, a.geom b.attr FROM poly a JOIN poly b on a.attr is null and b.attr is not null and st_intersects(a.geom, b.geom) UNION ALL SELECT --partie recursive : on récupére les enregistrements sans attributs voisins des enregistrements produits par le cas de base a.id, a.geom, r.attr FROM poly a RIGHT JOIN r ON a.id <> r.id --on veut éviter de reprendre les polygones déja traités and a.attr is null and r.attr is not null and st_intersects(a.geom, b.geom) ), x as ( select * from r LIMIT 1000 -- on mets généralement une limit au resultat produit par une requête recursive -- ca permet de tester qu'elle fonctionne et d'éviter qu'elle ne tourne indéfiniment -- si on a mal ecrit la requête ) UPDATE poly a SET attr = x.attr FROM (select id,max(attr) from x GROUP BY id) x WHERE a.id = x.id ;
Les CTE récursives se composent généralement d'une partie de base (dans le code la requête au dessus du UNION ALL) et d'une partie recursive (sous le UNION ALL). La CTE s'arrête une fois qu'elle ne produit plus de nouveaux resultat (une nouvelle itération de la partie recursive ne renvoie pas d'enregistrement).
Une difficulté de votre demande vient du fait qu'il peut potentiellement y avoir plusieurs candidats pour chaque polygone sans attribut. Les GROUP BY et LATERAL JOIN n'étant pas autorisés dans les CTE recursives, la solution que je propose utilise la CTE pour générer toutes les combinaisons possibles et la sous requête de la clause FROM de la commande UPDATE selectionne la valeur à attribuer (ici j'ai choisi la fonction max mais on peut en choisir une autre ou faire cela de façon non déterministe).
Je ne suis pas sûr des bonnes performances de la requête, si elle fonctione.
Dernière modification par tumasgiu (Hier 12:05)
Hors ligne
#3 Hier 12:22
- ppluvinet
- Participant assidu
- Lieu: VALENCE
- Date d'inscription: 6 Aug 2007
- Messages: 615
Re: UPDATE avec un WITH RECURSIVE
Merci beaucoup pour avoir pris le temps de me répondre.
Il faudra que je l'adapte encore car mon problème est un peu plus complexe. En effet, prendre la valeur du voisin est un peu trop simpliste !!
Je testerai et ferai un retour. Grand merci,
Pascal PLUVINET
Hors ligne
#4 Hier 13:12
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1553
Re: UPDATE avec un WITH RECURSIVE
Bonjour,
Si les polygones à corriger intersectent des voisins dont ils doivent prendre une valeur, pourquoi ne pas utiliser st_clusterIntersecting ?
Vous aurez des groupes de polygones qui se touchent et dans chaque groupe, les polygones avec attribut null et des voisins avec l'attribut que voulez prendre.
(je sens bien que je n'ai pas tout compris à votre pb )
Nicolas
Hors ligne
#5 Hier 13:15
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1157
Re: UPDATE avec un WITH RECURSIVE
@Nicolas,
de ce que j'ai cru comprendre il y a des polygones dont aucun voisin ne possède d'attribut, d'ou l'approche itérative.
Hors ligne
#6 Hier 13:18
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1553
Re: UPDATE avec un WITH RECURSIVE
Vous auriez un exemple visuel ?
Nicolas
Hors ligne
#7 Hier 13:21
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1553
Re: UPDATE avec un WITH RECURSIVE
@Nicolas,
de ce que j'ai cru comprendre il y a des polygones dont aucun voisin ne possède d'attribut, d'ou l'approche itérative.
Ok merci pour la précision. Si ce polygone n'a que des voisins sans attribut, alors le voisin du voisin sera connecté avec un polygone ayant un attribut, qui apparaitra donc dans le cluster et dont on pourra recupérér l'attribut, non ?
Nico
Hors ligne
#8 Hier 13:32
- tumasgiu
- Membre
- Lieu: Ajaccio
- Date d'inscription: 5 Jul 2010
- Messages: 1157
Re: UPDATE avec un WITH RECURSIVE
tumasgiu a écrit:@Nicolas,
de ce que j'ai cru comprendre il y a des polygones dont aucun voisin ne possède d'attribut, d'ou l'approche itérative.
Ok merci pour la précision. Si ce polygone n'a que des voisins sans attribut, alors le voisin du voisin sera connecté avec un polygone ayant un attribut, qui apparaitra donc dans le cluster et dont on pourra recupérér l'attribut, non ?
Nico
Tout à fait. Je pense que l'approche avec st_clusterintersectings est valide. Après cela depend peut être de la façon dont on veut que les attributs se "diffusent" de voisin en voisin ? Il faudrait plus de précision sur le problème
En apparté je viens de voir que les fonctions de cluster ont maintenant une version utilisable dans les window function, .
Dernière modification par tumasgiu (Hier 13:34)
Hors ligne
#9 Hier 15:56
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1553
Re: UPDATE avec un WITH RECURSIVE
En apparté je viens de voir que les fonctions de cluster ont maintenant une version utilisable dans les window function, .
Ouiiii trop bien (et aussi les nouvelles fonctions de coverage, pour tester et cleaner ses couches)
Hors ligne