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.
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 ».
Merci beaucoup.
J’ai modifié 1-n dans le texte mais si je modifie le titre ça ouvre une boîte de Pandore au niveau du référencement. Je retiens pour le futur.
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…
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)
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….
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 »?
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.
Merci, votre tuto m’a beaucoup aidé.
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.
Les infobulles sont en HTML et peuvent afficher autant d’informations que vous souhaitez.
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.
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
Évitez les caractères spéciaux dans le nommage des tables (et des champs). Je pense qu’il faut remplacer le « – » par un « _ » dans Couche_virtuel-P1
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
Le message est assez explicite: la colonne n’existe pas ou elle ne s’appelle pas comme ça.
Vérifiez dans propriétés de la couche le nom exact de votre champ
Merci beaucoup ça marche bien
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
En ouvrant la table de la couche virtuelle, êtes-vous sûr qu’il n’y a qu’une seule ligne par code INSEE?
Oui ! C’est ce qui est très étonnant…