pdf - e-book - archive

1.4  Jointures

1.4.1  Principe

Nous utiliserons pour ce cours les données de A.2.

Si on souhaite connaître les numéros des modules pré-requis pour s’inscrire dans le module ’PL/SQL Oracle’, il nous faut tout d’abord le numéro de ce module :

SELECT numMod
FROM MODULE
WHERE nomMod = 'PL/SQL Oracle'

numMod
6

Ensuite, cherchons les numéros des modules pré-requis pour s’inscrire dans le module numéro 6,

SELECT numModPrereq 
FROM PREREQUIS 
WHERE numMod = 6;

numModPrereq
1
5

Et pour finir, allons récupérer les noms de ces modules,

SELECT nomMod 
FROM MODULE 
WHERE numMod IN (1, 5);

nomMod
Oracle
Merise

Vous êtes probablement tous en train de vous demander s’il n’existe pas une méthode plus simple et plus rapide, et surtout une façon d’automatiser ce que nous venons de faire. Il existe un moyen de sélectionner des données dans plusieurs tables simultanément. Pour traiter la question ci-dessus il suffisait de saisir :

SELECT m2.nomMod 
FROM MODULE m1, MODULE m2, PREREQUIS p 
WHERE m1.numMod = p.numMod 
AND m2.numMod = p.numModprereq 
AND m1.nomMod = 'PL/SQL Oracle';

nomMod
Oracle
Merise

Le but de ce chapitre est d’expliciter ce type de commande.

1.4.2  Produit cartésien

L’instruction SELECT ... FROM ... peut s’étendre de la façon suivante :

SELECT <listecolonnes>
FROM <listetables>


L’exemple ci-dessous vous montre le résultat d’une telle commande.

SELECT * 
FROM PROPOSER, PRODUIT;

numfou numprod prix numprod nomprod
2 3 1 1 Bocal de cornichons
2 2 2 1 Bocal de cornichons
2 1 3 1 Bocal de cornichons
1 1 2 1 Bocal de cornichons
2 3 1 2 Tube de dentifrice
2 2 2 2 Tube de dentifrice
2 1 3 2 Tube de dentifrice
1 1 2 2 Tube de dentifrice
2 3 1 3 Flacon de lotion anti-escarres
2 2 2 3 Flacon de lotion anti-escarres
2 1 3 3 Flacon de lotion anti-escarres
1 1 2 3 Flacon de lotion anti-escarres
2 3 1 4 Déodorant fraîcheur 96 heures
2 2 2 4 Déodorant fraîcheur 96 heures
2 1 3 4 Déodorant fraîcheur 96 heures
1 1 2 4 Déodorant fraîcheur 96 heures

Placer une liste de tables dans le FROM revient à former toutes les combinaisons de lignes possibles. Cependant, cela a relativement peu de sens.

1.4.3  Jointure

Il serait plus intéressant, dans le cas présent, de ne voir s’afficher que des lignes dont les numéros de produits concordent. Pour ce faire, il suffit d’utiliser WHERE. Par exemple,

SELECT * 
FROM PROPOSER, PRODUIT
WHERE PROPOSER.numprod = PRODUIT.numprod;

numfou numprod prix numprod nomprod
1 1 2 1 Bocal de cornichons
2 1 3 1 Bocal de cornichons
2 2 2 2 Tube de dentifrice
2 3 1 3 Flacon de lotion anti-escarres

Nous avons mis en correspondance des lignes de la table proposer avec des lignes de la table produit en utilisant le fait que numprod est une clé étrangère dans proposer. Comme la colonne numprod apparaît deux fois dans la requête, il est nécessaire de la préfixer par le nom de la table de sorte que chaque colonne puisse être désignée de façon non ambiguë. Si on veut mettre face à face les noms des produits et les noms des fournisseurs, il suffit de saisir la requête

SELECT nomfou,  nomprod
FROM PRODUIT, FOURNISSEUR, PROPOSER
WHERE PRODUIT.numProd = PROPOSER.numProd
AND FOURNISSEUR.numFou = PROPOSER.numFou;

nomfou nomprod
Bocaux Gérard Bocal de cornichons
Paramédical Gisèle Bocal de cornichons
Paramédical Gisèle Tube de dentifrice
Paramédical Gisèle Flacon de lotion anti-escarres

1.4.4  Jointures réflexives

En utilisant la syntaxe suivante, il est possible de renommer les tables,

FROM <table_1> <table_1_renommee>, ..., <table_n> <table_n_renommee>

Reformulons la requête ci-dessus,

SELECT nomfou,  nomprod
FROM PRODUIT p, FOURNISSEUR f, PROPOSER pr
WHERE p.numProd = pr.numProd
AND f.numFou = pr.numFou;

nomfou nomprod
Bocaux Gérard Bocal de cornichons
Paramédical Gisèle Bocal de cornichons
Paramédical Gisèle Tube de dentifrice
Paramédical Gisèle Flacon de lotion anti-escarres

Le renommage permet entre autres de faire des jointures réflexives, c’est à dire entre une table et elle même. Par exemple, en reprenant la table intervalle,

SELECT * FROM INTERVALLE;

borneInf borneSup
0 30
2 3
2 56
5 10
7 32
8 27
12 3
12 30
21 8
34 26

La commande ci-dessous affiche tous les couples d’intervalles ayant une borne en commun,

SELECT * FROM INTERVALLE i, INTERVALLE j
WHERE (i.borneInf = j.borneInf AND i.borneSup < j.borneSup)
OR (i.borneInf < j.borneInf AND i.borneSup = j.borneSup);

borneInf borneSup borneInf borneSup
0 30 12 30
2 3 2 56
2 3 12 3
12 3 12 30