Jointures 1-n dans QGis: les couches virtuelles

Une des techniques les plus répandues en SIG pour pouvoir traiter des données non spatiales est celle de la jointure. On utilise une couche géographique, possédant des géométries, comme support d’une autre couche ne possédant pas de données de localisation. Pour faire cela, on utilise un champ commun aux deux tables, qui permet de « joindre » les enregistrements de la table géographique à ceux de la table non géographique. On créé ainsi une nouvelle table virtuelle ou les attributs de la table non géographique peuvent être utilisés pour être cartographiés avec la géométrie de la première table. Pour que cette jointure marche il faut que pour un enregistrement de la table géographique on retrouve un enregistrement dans la table non géographique, ou qu’on n’en trouve pas. Car si l’on trouve plus d’un, la jointure ne peut pas marcher. On parle alors de « relation » entre les tables et non de « jointure ».

Pendant longtemps, les logiciels SIG n’ont permis que de travailler avec des jointures. Les relations ne supportaient pas la plupart des opérateurs spatiaux applicables aux jointures.

Une des raisons de cette limitation était le sous-ensemble restreint du langage SQL applicable aux couches géographiques. Que ce soit sur les fichiers shapefile, ou autres, les requêtes applicables se limitaient à une clause préformatée  de type « SELECT * FROM la_table WHERE » et où on pouvait construire la fin de la requête, c’est à dire la clause WHERE.

Pour pouvoir créer une table virtuelle avec plusieurs enregistrements de la table B correspondants à un enregistrement de la table A (cardinalité de type 1,n) il faut utiliser la capacité de jointure de tables du SQL et donc, utiliser deux tables dans la requête. Ceci est possible dans QGis aujourd’hui (ça n’a pas toujours été le cas), en utilisant les « couches virtuelles ». Elles sont apparues sous forme de plugin dans la version 2.10, et intégrées aux corps de QGis dans la version 2.14 .

Les couches virtuelles de QGis

Fonctionnalités des couches virtuelles

•Vous pouvez créer une nouvelle couche virtuelle avec le bouton « New virtual layer »:
•Une couche virtuelle peut être créée à partir d’une sélection de couche (clic droit dans la fenêtre couche)

•Si vous voulez filtrer une couche avec une jointure, Qgis proposera de créer une couche virtuelle

•Dans DBMANAGER, il y a une nouvelle entrée « Virtual Layers » où vous pouvez utiliser la Fenêtre SQL pour créer une couche virtuelle

La génération des couches virtuelles est sauvegardée dans le fichier projet. La couche virtuelle se comporte comme une table native, notamment avec les champs issus d’une jointure.

Utilisation des couches virtuelles

Prenons un exemple:

Nous disposons d’un fichier Excel contenant les différentes aires communales (campings, grandes surfaces,naturelles, stationnements,…). Ce tableau a une colonne INSEE où l’on trouve le code Insee de la commune sur laquelle se trouve l’aire.

Nous disposons d’un shapefile des communes sous forme de polygones, dans lequel nous trouvons un attribut INSEE_COM avec le code Insee de la commune.

Ce que nous souhaitons c’est d’avoir une couche où chaque aire soit représentée par le polygone de la commune correspondante. Au lieu d’avoir les X polygones de la couche communes nous voulons avoir les Y polygones correspondants aux Y lignes de la table Excel des aires communales.

Nous chargeons la couche Communes dans QGis, ainsi que la table Excel CCAires. Pour charger la table Excel vous devez activer et utiliser le plugin Spreadsheet Layers.

Pour créer la couche virtuelle, on clique sur le bouton Ajouter/Editer couche virtuelle

Nous utilisons le bouton Importer pour ajouter les deux couches dans la liste des Couches intégrées.

Dans la fenêtre Requête, on rentre la commande SQL suivante:

SELECT * FROM communes29, CCAires  where INSEE_COM = INSEE

Vous pouvez (et devez) tester la syntaxe de votre requête SQL avec le bouton Tester

On clique sur OK et la couche virtuelle est ajoutée à la carte.

Remarquez les deux communes absentes, car elles n’ont pas d’aire communale dans le fichier Excel.

Si on affiche la table attributaire de la couche virtuelle:

On peut voir que plusieurs enregistrements correspondent à une même commune, et que le nombre d’enregistrements (419) correspond au nombre de lignes du tableau Excel et non au nombre des communes du shapefile (283).

On peut aller plus loin et ajouter une clause WHERE pour ne sélectionner qu’une partie des aires communales, par exemple les campings

On obtient seulement 148 enregistrements, correspondant au nombre de campings présents dans le tableau Excel.

Si cet article vous a intéressé et que vous pensez qu'il pourrait bénéficier à d'autres personnes, n'hésitez pas à le partager sur vos réseaux sociaux en utilisant les boutons ci-dessous. Votre partage est apprécié !

19 thoughts on “Jointures 1-n dans QGis: les couches virtuelles

  1. Toujours aussi didactique, c’est un plaisir à lire.
    Concernant la cardinalité de type 1-n, autant écrire 1, n ou (1, n), on a ainsi moins tendance à lire « un moins n ».

  2. Bonjour, c’est effectivement très clair mais je n’y arrive pas 🙁

    Voici ma requête sql :

    select * from limites-communales, test where COMMUNE=nom

    Et j’ai ce message d’erreur : Query execution error on DROP TABLE IF EXISTS « test »; CREATE VIRTUAL TABLE « test » USING QgsVLayer(‘ogr’,’C:/Users/Etude/Downloads/carto/test.csv.vrt’,UTF-8): 1 – near « . »: syntax error

    Limites-communales est un shp avec mes limites de communes
    il est dans C:\Users\Etude\Downloads\carto\limites-communales.shp

    test est un fichier csv avec parfois plusieurs enregistrements pour une même commune :
    il est dans C:/Users/Etude/Downloads/carto/test.csv.vrt

    (pourquoi il y a il des « slash » dans un cas et des « antislashs » dans l’autre ? )

    Merci d’avance si vous voyez une solution…

  3. Et si j’utilise un fichier dBase au lieu d’un csv, j’ai ce message d’erreur : Query preparation error on PRAGMA table_info(_tview)

  4. J’ai trouvé !!!! (mais ca peut servir à d’autres). J’essayais de relier mes 2 tables à l’aide de champ texte. En utilisant 2 champs de nobres entier ca marche parfaitement.
    Quelle serait la syntaxe à utiliser pour relier avec des champs textes ?
    merci….

    1. C’est aussi mon problème: est-ce un problème de syntaxe, ou est-il simplement impossible de faire une telle jointure sur une colonne de type « char »?

      1. Il y a effectivement un bug sur la jointure de deux champs texte, seulement s’ils sont de type NOT NULL
        Si le champ est character varying ou text mais il n’est pas de type NOT NULL, ça fonctionne. Dans le cas contraire, la table virtuelle résultante apparaît vide.
        Il faut donc, soit enlever le NOT NULL, soit créer un nouveau champ texte.

  5. merci pour ce tuto, très clair. Il m’a beaucoup aidé aussi. J’aurais une question supplémentaire, comment faire pour afficher les informations dans l’infobulle après? car l’infobulle ne prend qu’une information à la fois.

  6. Merci pour la réponse. pourriez vous m’indiquer comment faire, svp? j’ai par exemple trois lignes pour une seule commune, je voudrais afficher les informations de ces trois lignes au clic de la commune.

  7. Bonjour
    Je n’y arrive pas à refaire la requête
    Ici ma requête : SELECT*FROM parcelle_couche, Couche_virtuel-P1 WHERE geo_parcel_COM=geo_parcel
    Message d’erreur :
    Query execution error on CREATE TEMP VIEW _tview AS SELECT*FROM parcelle_couche, Couche_virtuel-P1 WHERE geo_parcel_COM=geo_parcel: 1 – near « -« : syntax error
    Je n’arrive pas à trouver la solution
    Si vous pouvez m’aider
    Merci

  8. Bonjour
    J’ai modifié ma requête
    SELECT * FROM parcelle_couche, Couche_parc_Feuil1 WHERE geo_parcel_COM=geo_parcel
    Message d’erreur
    Query preparation error on PRAGMA table_info(_tview): no such column: geo_parcel_COM

  9. Bonjour,

    Merci pour les explications.

    Ma table virtuelle se comporte comme une jointure 1-1 !

    Pour reprendre votre exemple, une seule aire a été jointe à la couche commune, et non pas toutes les aires de la commune.

    Auriez-vous une explication s’il vous plait ?

    Merci et bonne journée,

    Alex

Répondre à Alex Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *