|
Chapitre 12 : la
notion de jointure |
|
|
1 - Introduction |
|
|||||||||||||||||||||||||||||||||||
|
|
|
Dans
une base de données relationnelle, les informations sont réparties sur un grand
nombre de tables. Il est donc fréquent qu'une requête porte sur deux tables
(ou plus), liées par une (ou plusieurs) relation(s). La notion de jointure précise comment fonctionnent cette
(ou ces) relation(s) lors de l'exécution de la requête. |
|
||||||||||||||||||||||||||||||||||
|
|
|
Comme
pour les autres chapitres de ce tutoriel (ou tutorial, ou cours en ligne),
nous utilisons le SGBD Access comme support pratique. Pour bâtir un exemple,
nous faisons appel aux deux tables "Personnes" et
"Communes" dont nous nous sommes déjà servis au chapitre 4.
Nous remplissons ces deux tables comme le montre la
figure ci-dessous. Précisons que le champ "Commune" de la table
"Personnes" n'a pas été rendu obligatoire (le Null
est autorisé), si bien qu'il peut arriver qu'une commune ne soit pas
attribuée à une personne, comme c'est le cas pour Jeanne Dupont. |
|
||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||
|
|
|
Les
deux tables sont liées par une relation, assurée via un code masqué. Cette relation
apparaît dans la fenêtre "Relations", comme le montre la figure
ci-dessous. |
|
||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||
|
|
2 - La relation |
|
|
|
|
|
Si
nous ajoutons les deux tables précitées à la fenêtre de création d'une
requête, nous constatons que la relation qui les lie est toujours présente. |
|
|
|
|
Dans
la fenêtre de création d'une requête, nous pouvons supprimer cette relation.
La procédure est identique à celle pratiquée dans la fenêtre
"Relations" : nous effectuons un clic droit sur la relation,
et nous choisissons "Supprimer". Nous fermons la fenêtre de
création de la requête, et nous enregistrons cette dernière. |
|
|
|
|
Si
nous ouvrons la fenêtre "Relations", nous constatons que la
relation qui lie les deux tables existe toujours. Cette relation est
en quelque sorte une propriété des deux tables. |
|
|
|
|
La
suppression que nous avons effectuée est liée à une requête particulière.
Elle n'a d'effet que lors de l'exécution de la requête. Ce n'est pas une
propriété des deux tables, mais une propriété de la requête. |
|
|
|
|
Remarque
: même s'il n'existe pas de relation entre deux tables, le SGBD Access en
crée une automatiquement lorsque vous ajoutez ces deux tables à la fenêtre de
création d'une requête, à condition que ces tables aient chacune un champ du
même nom et du même type de données, et qu'un des deux champs possède une clé
primaire. |
|
|
|
|||
|
|
3 - Le produit vectoriel |
|
|
|
|
|
Nous
rouvrons la requête précédente en mode "Modification". Nous vérifions
qu'aucune relation n'apparaît entre les deux tables. Dans la grille, nous
introduisons les champs "Nom" et "Prénom" de la première
table, et les champs "Commune" et "Code postal" de la
seconde. La feuille de données résultante contient 20 lignes ! Que
s'est-il passé ? |
|
|
|
|
Le
SGBD a associé chaque ligne de la première table (il y en a 4) à chaque
ligne de la seconde (il y en a 5). On dit qu'il a effectué le produit vectoriel des deux tables. L'absence
de relation fait que le SGBD ne sait pas comment il doit associer les lignes
des deux tables ; de ce fait, il réalise toutes les combinaisons
possibles. |
|
|
|
|
Il
faut faire attention au fait que le produit vectoriel peut nous conduire à créer
des tables gigantesques : le produit de deux tables contenant chacune
1.000 enregistrements est une table possédant 1 million de
lignes ! |
|
|
|
|
En
pratique, on n'utilise pas le produit vectoriel, sauf dans des cas très rares,
comme par exemple pour réunir dans une seule table des comptages isolés. Ces
derniers se présentent en effet sous forme de tables à une seule ligne, et
l'on peut en faire le produit vectoriel sans risque, car le résultat est
alors une table à une seule ligne. |
|
|
|
|||
|
|
4 - La jointure interne |
|
|||||||||||||||||
|
|
|
Dans
la fenêtre de création de la requête, nous rétablissons la relation entre les
deux tables. Cette fois, la feuille de données résultante ne contient plus
que 3 lignes, comme le montre la figure ci-dessous. |
|
||||||||||||||||
|
|
|||||||||||||||||||
|
|||||||||||||||||||
|
|
|||||||||||||||||||
|
|
|
Nous
constatons que ne figurent dans la table résultante que les enregistrements
qui sont présents dans les deux tables. La personne Dupont Jeanne, dont la
commune n'est pas précisée, est absente du résultat. Les villes Grenoble
(38001) et SMH, auxquelles ne correspond aucune personne, sont également
absente. Le SGBD a traité la relation entre les deux tables comme une jointure interne. |
|
||||||||||||||||
|
|
|
Effectuons
un clic droit sur la relation, et sélectionnons "Propriétés de la
jointure". La fenêtre du même nom s'affiche ; elle se présente
comme le montre la figure ci-dessous. Bien que le
terme ne soit pas présent, l'option 1 de la fenêtre correspond
effectivement à la jointure interne. |
|
||||||||||||||||
|
|
|||||||||||||||||||
|
|
|||||||||||||||||||
|
|
|||||||||||||||||||
|
|
|
Remarque
: dans la requête précédente, le champ "Commune" est issu de la
table "Communes". S'il provenait de la table "Personnes",
le résultat s'afficherait de la même façon. C'est seulement en exportant la
table que l'on peut s'apercevoir que dans le second cas, le champ contient un
code au lieu d'un nom de commune. |
|
||||||||||||||||
|
|
|||||||||||||||||||
|
|
5 - La jointure gauche |
|
|||||||||||||||||||||
|
|
|
La
fenêtre "Propriétés de la jointure", représentée ci-dessus, nous fournit
deux autres options. Nous activons le bouton 2 et nous validons par
"OK". La requête se présente maintenant comme le montre la figure
ci-dessous. Nous avons affaire à une jointure
gauche. Pour le signaler, la liaison prend la forme d'une
flèche... dirigée vers la droite. |
|
||||||||||||||||||||
|
|
|||||||||||||||||||||||
|
|
|||||||||||||||||||||||
|
|
|||||||||||||||||||||||
|
|
|
Si
nous basculons en mode feuille de données, nous obtenons le résultat
suivant : |
|
||||||||||||||||||||
|
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
|
|||||||||||||||||||||||
|
|
|
Cette
fois, le SGBD a conservé tous les enregistrements de la table
"Personnes", et il leur a associé les enregistrements disponibles
dans la table "Communes". Comme nous n'avons pas précisé de critère
de sélection, tous ces enregistrements ont été conservés. |
|
||||||||||||||||||||
|
|
|||||||||||||||||||||||
|
|
6 - La jointure droite |
|
|||||||||||||||||||||||||
|
|
|
Dans
la fenêtre "Propriétés de la jointure", nous activons le
bouton 3 et nous validons par "OK". Nous avons maintenant
affaire à une jointure droite. Pour
le signaler, la liaison prend la forme d'une flèche... dirigée vers la
gauche. |
|
||||||||||||||||||||||||
|
|
|
Si
nous basculons en mode feuille de données, nous obtenons le résultat
suivant : |
|
||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||
|
|
|
Cette
fois, le SGBD a conservé tous les enregistrements de la table
"Communes", et il leur a associé les enregistrements disponibles
dans la table "Personnes". Comme nous n'avons pas précisé de
critère de sélection, tous ces enregistrements ont été conservés. |
|
||||||||||||||||||||||||
|
|
|
Conclusion :
le résultat d'une requête multi-table dépend du type de jointure choisi. Par
défaut, c'est la jointure interne qui s'applique. |
|
||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||
|
|
7 - La requête de non correspondance |
|
||||||||||||||||||
|
|
|
La
requête de non correspondance
constitue une application importante de la notion de jointure. Elle met en
jeu deux tables ayant en commun un champ possédant le même type de données,
et doté des mêmes propriétés (mais pas forcément du même nom). La requête de
non-correspondance ne conserve un enregistrement de la première table que si
le contenu du champ n'est pas présent dans la seconde table. Les deux
tables n'ont pas besoin d'être liées au préalable par une relation, cette
dernière sera créée en même temps que la requête. |
|
|||||||||||||||||
|
|
|
Pour
construire un exemple simple, nous créons deux tables à un seul champ,
contenant des prénoms, et intitulées "Prénoms1" et
"Prénoms2". Les tables se présentent ainsi : |
|
|||||||||||||||||
|
|
||||||||||||||||||||
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
|
Nous
recherchons les prénoms de la première table qui sont absents de la seconde. Pour
ce faire, nous devons passer en revue tous les prénoms de la première
table, et regarder s'ils sont ou non dans la seconde. Pour créer la requête
correspondante, nous songeons donc à utiliser une jointure gauche. |
|
|||||||||||||||||
|
|
|
Pour
bien comprendre ce qui se passe, nous pouvons décomposer en deux temps le
fonctionnement de la requête. D'abord, le SGBD sélectionne tous les
prénoms de la première table, et leur associe les prénoms de la seconde table
quand ils sont identiques. Le résultat de cette première étape peut être
représenté ainsi : |
|
|||||||||||||||||
|
|
||||||||||||||||||||
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
|
Il
faut maintenant que le SGBD applique un critère de sélection, pour ne
conserver que les lignes dont la deuxième colonne est vide. Nous
plaçons donc le critère "Est Null" dans
la colonne relative au champ "Prénom" de la seconde table. |
|
|||||||||||||||||
|
|
|
En
définitive, nous obtenons la requête représentée sur la figure ci-dessous (remarquez
la flèche qui traduit la jointure gauche). Nous avons supprimé l'affichage de
la seconde colonne, car il conduirait à créer une colonne vide dans la
feuille de données résultante. |
|
|||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
|
Si
nous basculons en mode feuille de données, nous obtenons le résultat suivant
: |
|
|||||||||||||||||
|
|
||||||||||||||||||||
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
|
Il
est indispensable, dans un requête de non correspondance, de ne pas se
tromper sur le type de jointure à utiliser. Ainsi, si nous choisissons la
jointure interne (par défaut), le SGBD ne sélectionne que les prénoms qui
sont simultanément présents dans les deux tables. Le résultat de cette étape
intermédiaire est représenté ci-dessous : |
|
|||||||||||||||||
|
|
||||||||||||||||||||
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
|
Lorsque
nous appliquons le critère "Est Null" à
la deuxième colonne, le SGBD ne conserve que les lignes pour lesquelles
la deuxième colonne est vide. Comme il n'y en a pas, la feuille de
données résultante ne contient aucun enregistrement -- ce que l'expérience confirme. |
|
|||||||||||||||||
|
|
|
Si
nous utilisons la jointure droite, le SGBD sélectionne tous les prénoms de la
seconde table, et seulement ceux de la première table qui se trouvent dans la
seconde. Cette étape intermédiaire peut être représentée ainsi : |
|
|||||||||||||||||
|
|
||||||||||||||||||||
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
|
Puis
le SGBD élimine les lignes pour lesquelles la seconde colonne est vide.
Comme il n'y en a pas, la feuille de données résultante ne contient aucun enregistrement
-- ce que l'expérience confirme. |
|
|||||||||||||||||
|
|
|
Si
le raisonnement relatif à la requête de non correspondance vous paraît ardu,
ne vous inquiétez pas : vous n'êtes pas le seul. C'est la raison pour laquelle
Microsoft a créé un assistant pour ce type de recherche. Vous le trouverez
dans la fenêtre "Base de données", l'objet "Requêtes"
étant sélectionné. Vous cliquez sur l'icône |
|
|||||||||||||||||
|
|
||||||||||||||||||||
|
|
8 - La requête de correspondance |
|
||||
|
|
|
La
requête de correspondance est en
quelque sorte le complément de la précédente. Elle met en jeu deux tables
ayant en commun un champ possédant le même type de données, et doté des mêmes
propriétés (mais pas forcément du même nom). Elle ne conserve un
enregistrement de la première table que si le contenu du champ est présent
dans la seconde table. La requête de correspondance constitue elle aussi une
application courante de la notion de jointure. Comme précédemment, les deux
tables n'ont pas besoin d'être liées au préalable par une relation, cette
dernière étant créée en même temps que la requête. |
|
|||
|
|
|
Cette
fois, nous recherchons les prénoms de la première table qui sont présents
dans la seconde. Pour créer la requête correspondante, il nous faut utiliser
une jointure interne. Cela suffit, il n'est pas utile de préciser un
critère. Nous obtenons ainsi la requête représentée sur la figure ci-dessous. |
|
|||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
Si
nous basculons en mode feuille de données, nous obtenons le résultat suivant,
complémentaire de celui obtenu avec la requête de non correspondance : |
|
|||
|
|
||||||
|
||||||
|
|
||||||
|
|
|
Exercez-vous
à prévoir ce qui se passe si vous vous trompez de jointure, et vérifiez si l'expérience
confirme vos prédictions. |
|
|||
|
|
|
La
requête de correspondance étant plus facile à créer que la requête de
non-correspondance, l'éditeur d'Access n'a pas prévu d'assistant pour aider à
la créer. Cependant, vous pouvez utiliser l'assistant précédent, et changer
simplement la condition "Est Null" par
son contraire "Est Pas Null". C'est
inutilement compliqué, mais cela marche. |
|
|||
|
|
||||||
|
|
9 - Conclusion |
|
|
|
|
|
La
notion de jointure joue un rôle important dans les requêtes multi-tables, en
particulier dans les requêtes de correspondance et de non correspondance. |
|
|
|
|
Si
l'opérateur ne précise pas le type de jointure, c'est la jointure interne que
le SGBD applique par défaut. |
|
|
|
|||