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é ?

#1 Wed 07 December 2022 10:47

yaks48
Participant occasionnel
Date d'inscription: 3 Nov 2022
Messages: 17

QGIS: suppression conditionnelle de doublons SQL

Bonjour,
Je travaille sous pgAdmin 4 et dbManager (QGIS 3.28.1)
dans le cadre de ma requête SQL qui consiste dans les grosses lignes à regarder l'intersection de plusieurs zonages avec certaines parcelles, je cherche à supprimer certains doublons particuliers : des doublons sur certains champs lorsque d'autres champs sont égaux à une valeur 'ns' (non significative).
Par exemple, je cherche à éliminer les doublons vis-à-vis de ma jointure sur natura2000 et znieff (imaginons respectivement 0 (car pas d'intersection avec mes parcelles vis-à-vis de Natura2000) et 1 pour znieff, mais la même géométrie est répétée plusieurs fois à cause d'une autre intersection avec une autre table nommée t1.
L'intersection renvoie soit "NULL" si pas d'intersection, soit 'ns' si non significatif, soit du texte si l'intersection est significative.

je veux supprimer les lignes qui doublonnent sur n2000 et znieff ET qui ont un 'ns' ET dont une ligne au moins est NULL ou <> 'ns' pour l'intersection avec t1
je ne veux pas supprimer une géométrie qui n'aurait qu'une ligne dont un 'ns' pour l'intersection avec t1.

je n'arrive pas à trouver de solution adaptée en SQL sur le forum ou sur internet

J'espère être clair, désolé je suis débutant en SQL j'espère bien m'exprimer

Merci d'avance énormément

Hors ligne

 

#2 Wed 07 December 2022 20:17

Mathieu Denat
Participant actif
Lieu: Montpellier
Date d'inscription: 5 May 2010
Messages: 110

Re: QGIS: suppression conditionnelle de doublons SQL

Bonsoir,

Je ne suis pas sur d'avoir saisi en détail les subtilités (je n'ai pas saisi à quel comment intervient t1), une requête aurait été bienvenue! wink

Si j'ai bien compris, l'idée est de tester l'intersection d'une couche avec des zonages.
Personnellement je procéderais par étape (je pars du postulat que les parcelles ont un identifiant unique : id_parcelle, et que vous travaillez sous postgreSQL):
1. sélection des tables qui intersectent mon zonage, je garde l'id unique et l'info du zonage 1
2. idem pour le zonage 2
3. idem pour le zonage 3, etc, etc
4. je joins les différentes tables à ma table parcelle sur leur identifiant

Code:

with

--pour les znieff
znieff as (
select distinct p.*, 'true'::boolean znieff
from parcelles p
join znieff tj on st_intersects(p.geom,tj.geom)
)

--pour natura2000
,n2000 as (
select distinct p.id, 'true'::boolean n2000
from parcelles p
join natura_2000 tj on st_intersects(p.geom,tj.geom)
)

---etc, etc ajouter autant de blocs que de zonages

-- étape finale: tout joindre
select distinct p.*, z.znieff, n.n2000
from parcelle p
left join znieff z  on p.id_parcelle = z.id_parcelle
left join n2000 n on p.id_parcelle = n.id_parcelle

Le résultat attendu est du type:
geom, id_parcelle, znieff, n2000, etc.
znieff et n2000 sont des booléens (valeur vrai/faux ou null).

Cette couche peut être intersectée avec la couche t1 (et éventuellement filtré au préalable).

J'espère apporter un début de solution, bonne continuation.


Mathieu
C'est en forgeant qu'on devient forgeron

Hors ligne

 

#3 Fri 09 December 2022 10:25

yaks48
Participant occasionnel
Date d'inscription: 3 Nov 2022
Messages: 17

Re: QGIS: suppression conditionnelle de doublons SQL

Bonjour Mathieu,
Merci beaucoup pour votre réponse.
Je vais essayer votre solution et voir ce que ça donne.

pour l'instant j'ai construit ce code (t1 correspond en fait au rpg) :

Code:

 create table mes_resultats_temporaires as

select mes_parcelles.geom, mes_parcelles.numero, 

CASE WHEN st_area(st_intersection(mes_parcelles.geom, rpg.geom)) > 0.05*st_area(mes_parcelles.geom) 
    THEN rpg.libelle 
    WHEN st_area(st_intersection(mes_parcelles.geom,rpg.geom)) between 0 and 0.05*st_area(mes_parcelles.geom)
    THEN 'ns'
    ELSE NULL 
    END as r_rpg,

row_number() OVER () as champ_uni

from mes_parcelles

left join rpg on st_intersects(mes_parcelles.geom, rpg.geom)

group by mes_parcelles.geom, mes_parcelles.numero, r_rpg
;

create table resultat_final as

select mes_resultats_temporaires.geom, mes_resultats_temporaires.numero, mes_resultats_temporaires.r_rpg

CASE WHEN sum(st_area(st_intersection(mes_resultats_temporaires.geom, znieff.geom))) > 0.05*st_area(mes_resultats_temporaires.geom) 
    THEN 1 ELSE 0 END as r_znieff,
CASE WHEN sum(st_area(st_intersection(mes_resultats_temporaires.geom, n2000.geom))) > 0.05*st_area(mes_resultats_temporaires.geom) 
    THEN 1 ELSE 0 END as r_n2000,
    
row_number() OVER () as champ_uni

from mes_resultats_temporaires

left join znieff on st_intersects(mes_resultats_temporaires.geom, znieff.geom)
left join n2000 on st_intersects(mes_resultats_temporaires.geom, n2000.geom)

group by mes_resultats_temporaires.geom, mes_resultats_temporaires.numero, r_znieff, r_n2000

je l'ai fait en deux fois car si je fais tout en une fois, il m'est arrivé d'avoir une parcelle qui avait 0 en znieff par exemple et la même parcelle qui avait 1 en znieff : une autre ligne a été créée car j'intersecte 2 entités de la table rpg. et du coup j'ai l'impression que postgre a sommé les surfaces deux fois, ce qui m'a fait dépasser les 5 % de la surface de ma parcelle analysée.

Et derrière, je cherche à éliminer les doublons sur tous les champs, sauf mon champ rpg : je veux éliminer les lignes contenant 'ns' au rpg, que si elles existent et que le reste est identique par ailleurs.

j'ai essayé cela mais je ne suis pas sûr ...

Code:

delete from resultat_final 
where champ_uni in(
        select champ_uni
            from (
                select *, row_number() over (partition by numero, r_znieff as rn
                from resultat_final ) x
            where (x.rn > 1 and rpg='ns') )

est-ce plus clair ?

merci beaucoup pour votre aide, je vais essayer votre méthode.

bien à vous

Hors ligne

 

Pied de page des forums

Powered by FluxBB