Compléments sur les jointures
La jointure est un opérateur fondamental en ce qu’il permet de naviguer parmi les données. Cependant, il est nécessaire de bien comprendre le fonctionnement des jointures pour écrire des requêtes correctes et efficaces.
Nous allons nous intéresser :
- à la pertinence d’utiliser une sous-requête plutôt qu’une jointure
- aux valeurs dérivées dans une jointure
- aux jointures généralisées
- à l’interprétation du résultat d’une jointure
Sous-requête vs jointure
Certaines conditions utilisant une sous-requête (SELECT emboité) peuvent s’exprimer à l’aide d’une jointure
Examinons 2 cas :
- Le cas des conditions d’association et de non association
- Le cas de sous-requête et de clé étrangère multicomposants
Equivalence
La requête suivante, qui renvoie les commandes passées par des clients de Grenoble :
1SELECT numero, dateCommande2FROM Commandes3WHERE numeroClient IN ( SELECT numero FROM Clients WHERE ville='Grenoble' ) ;
peut s’écrire également sous la forme d’une jointure :
1SELECT numero, dateCommande2FROM Commandes C, Clients CL3WHERE C.numeroClient = CL.numero4AND CL.ville='Grenoble' ;
Ou en utilisant la syntaxe JOIN
:
1SELECT numero, dateCommande2FROM Commandes C3JOIN Clients CL ON C.numeroClient = CL.numero4WHERE CL.ville='Grenoble' ;
Equivalence
La requête suivante renvoie les commandes qui contiennent un produit dont la quantité est inférieure à la quantité commandée pour le produit numéro 1 dans la commande numéro 3 :
1SELECT *2FROM Commandes3WHERE numero IN ( SELECT numeroCommande4 FROM Details5 WHERE numeroProduit = 1 AND quantite < (SELECT quantite6 FROM Details7 WHERE numeroProduit = 18 AND numeroCommande = 3) ) ;
Cette requête peut également s’écrire sous la forme de jointures uniquement :
1SELECT DISTINCT C.*2FROM Commandes C, Details D1, Details D23WHERE C.numero = D1.numeroCommande4AND D1.numeroProduit = 15AND D2.numeroProduit = 16AND D2.numeroCommande = 37AND D1.quantite < D2.quantite ;
Non équivalence
Cependant, la requête suivante, qui renvoie les commandes qui ne contiennent pas de produit numéro 1 : (qui pourrait aussi s’écrire avec un NOT EXISTS
)
1SELECT *2FROM Commandes3WHERE numero NOT IN ( SELECT numeroCommande4 FROM Details WHERE numeroProduit = 1 ) ;
Avec une jointure, on ne peut pas exprimer une condition de non-association
Intuitivement, on pourrait penser que la requête suivante serait similaire à la précédente :
1SELECT *2FROM Commandes C, Details D3WHERE C.numero = D.numeroCommande4AND D.numeroProduit != 1 ;
Mais cette requête ne renvoie pas les commandes qui ne contiennent pas le produit numéro 1. Elle renvoie les commandes qui contiennent un produit différent du produit numéro 1.
Comparaison des résultats
Pour s’en assurer, comparons les résultats des deux requêtes :
1SELECT numero2FROM Commandes3WHERE numero NOT IN ( SELECT numeroCommande4 FROM Details5 WHERE numeroProduit = 1 ) ;
Commandes |
---|
numero |
2 |
1SELECT C.numero2FROM Commandes C, Details D3WHERE C.numero = D.numeroCommande4AND D.numeroProduit != 1 ;
Commandes |
---|
numero |
1 |
1 |
2 |
2 |
3 |
3 |
3 |
3 |
4 |
5 |
5 |
Conclusion sur les sous-requêtes et les jointures
Conclusion
-
La jointure et la sous-requête permettent d’exprimer des conditions d’association entre lignes
-
En revanche, des conditions de non-association ne sont généralement exprimables que par des sous-requêtes, ainsi que par la forme
NOT EXISTS
Calculs sur les jointures
Une jointure permet également d’effectuer des calculs sur des quantités extraites de plusieurs tables
Le raisonnement est simple : la jointure constitue des lignes fictives, dont la clause SELECT
extrait des valeurs comme elle le ferait d’une ligne réelle issue d’une table
Par exemple, la requête suivant associe à chaque ligne de Details
le montant à payer pour la commande numéro 1:
1SELECT D.numeroCommande, D.numeroProduit, D.quantite, D.quantite * P.prix AS 'Montant'2FROM Details D, Produits P3WHERE D.numeroProduit = P.numero4AND D.numeroCommande = 1 ;
Commandes | |||
---|---|---|---|
numeroCommande | numeroProduit | quantite | Montant |
1 | 1 | 3 | 75 |
1 | 2 | 1 | 60 |
1 | 3 | 1 | 120 |
La requête suivante, elle, établit le montant de la commande numéro 1 :
1SELECT D.numeroCommande, SUM(D.quantite * P.prix) AS 'Montant total'2FROM Details D, Produits P3WHERE D.numeroProduit = P.numero4AND D.numeroCommande = 1 ;
Commandes | |
---|---|
numeroCommande | Montant total |
1 | 255 |
Autres conditions de jointures
Les conditions de jointures présentées jusqu’ici étaient fondées sur l’égalité des valeurs d’une clé étrangère avec celles d’un identifiant
Toutefois, toute comparaison peut servir à indiquer comment associer les lignes des tables concernées.
Autres conditions de jointures
L’exemple ci-dessous illustre une opération fréquente qui consiste à condenser de l’information de manière à la rendre plus lisible.
La table ci-dessous établit des intervalles successifs de valeurs de compte (minimum et maximum sur le compte) et leur attribut un code de classe de compte.
Classes_Comptes | ||
---|---|---|
minimumCompte | maximumCompte | codeCompte |
10000 | 32000 | A |
5000 | 10000 | B |
2000 | 5000 | C |
1000 | 2000 | D |
500 | 1000 | F |
0 | 500 | G |
-500 | 0 | U |
-1000 | -500 | V |
-2000 | -1000 | W |
-5000 | -2000 | X |
-10000 | -5000 | Y |
-32000 | -10000 | Z |
Comment associer à chaque client le code de son compte ?
La requête suivante permet de réaliser cette opération :
1SELECT numero, nom, compte, codeCompte2FROM Clients, Classes_Comptes3WHERE compte >= minimumCompte4AND compte < maximumCompte ;
Classes de comptes des clients | |||
---|---|---|---|
numero | nom | compte | codeCompte |
1 | Lebreton | 10000 | A |
2 | Vasseur | 1903 | D |
3 | Da Costa | -1500 | W |
4 | Rey | 3251 | C |
5 | Weiss | 0 | G |
7 | Lefevre | -1000 | V |
9 | Barda | -2000 | W |
8 | Jacques | -1750 | W |
Compréhension du résultat d’une jointure
La construction d’une requête qui utilise une ou plusieurs jointures peut s’avérer délicate.
Il est important de bien comprendre ce que représente le résultat d’une jointure.
La question est la suivante : sachant que toute ligne d’une table représente une entité du domaine d’application (un client, un achat, un détail, etc.), quelles entités les lignes d’une jointure représentent-elles ?
Par exemple, chaque ligne produite par l’évaluation de la requête :
1SELECT C.numero, C.nom, C.ville2FROM Clients C, Commandes Co3WHERE C.numero = Co.numeroClient ;
représente-t-elle :
- un client ?
- un client qui a passé une ou plusieurs commandes ?
- une commande ?
Réponse : des commandes
Règle générale
La règle relative à une jointure élémentaire, fondée sur l’égalité identifiant / clé étrangère est simple :
En bref : le résultat d’une jointure représente des entités de la table contenant la clé étrangère
Exemple :
Soit la requête suivante :
1SELECT Co.numero, Co.dateCommande, Co.numeroClient2FROM Commandes Co, Details D3WHERE Co.numero = D.numeroCommande ;
La clé étrangère de Details
est numeroCommande
, qui référence Commandes
.
Le résultat de cette requête représente donc des détails.
Identifiant de la jointure
Ce que nous venons de discuter conduit à une autre règle : l’identifiant du résultat de la jointure
1SELECT *2FROM TA, TB3WHERE TA.IA = TB.RA ;
est constitué des colonnes de l’identifiant primaire de TB
(soit IB
)
Si l’identifiant primaire de TB
n’est pas repris dans la sélection des colonnes, le résultat n’a pas d’identifiant.
Exemple :
1SELECT C.ville, P.nom2FROM Clients C, Commandes Co, Details D, Produits P3WHERE C.numero = Co.numeroClient4AND Co.numero = D.numeroCommande5AND D.numeroProduit = P.numero ;
Classes de comptes des clients | |
---|---|
ville | nom |
Meylan | T-shirt |
Meylan | Pantalon |
Meylan | Chaussures |
Meylan | Casquette |
Meylan | Sac à dos |
Paris | T-shirt |
Paris | Pantalon |
Paris | Chaussures |
Paris | Casquette |
Paris | Sac à dos |
Vizille | T-shirt |
Vizille | Pantalon |
Lille | T-shirt |
Lille | Pantalon |
Lille | Chaussures |
Lille | T-shirt |
Vizille | T-shirt |
Conclusion
- La jointure est un opérateur fondamental en SQL, qui permet de naviguer parmi les données.
- Les jointures permettent d’effectuer des calculs sur des quantités extraites de plusieurs tables.
- Il est nécessaire de bien comprendre le fonctionnement des jointures pour écrire des requêtes correctes et efficaces.
- Les jointures permettent d’exprimer des conditions d’association entre lignes.
- Les sous-requêtes permettent d’exprimer des conditions de non-association.
- Il est important de bien comprendre ce que représente le résultat d’une jointure.