Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
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 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 big_smile )

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

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

Hors ligne

 

#8 Hier 13:32

tumasgiu
Membre
Lieu: Ajaccio
Date d'inscription: 5 Jul 2010
Messages: 1157

Re: UPDATE avec un WITH RECURSIVE

Nicolas Ribot a écrit:
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, smile.

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

tumasgiu a écrit:

En apparté je viens de voir que les fonctions de cluster ont maintenant une version utilisable dans les window function, smile.


Ouiiii trop bien (et aussi les nouvelles fonctions de coverage, pour tester et cleaner ses couches)

Hors ligne

 

Pied de page des forums

Powered by FluxBB