Jointures
Jointures
Nous avons déjà vu des jointures de table lors de l'utilisation de la clause from
avec plusieurs sources. Notamment, nous avons vu que la jointure se fait via un produit cartésien, limité par les critÚres qu'on précise dans la clause where
.
Si on fait plusieurs jointures, la clause where
devient longue et difficile à gérer. En plus, contrÎler finement le type de jointure demande une attention exacte sur la clause where
.
SQL nous facilite cette tĂąche avec les clauses type join
, qui exĂ©cutent les jointures les plus utilisĂ©s, et nous permet de les exprimer de façon plus claire. La requĂȘte dessus peut ĂȘtre exprimĂ© avec, par exemple, des inner join
:
Avec cette formulation, la phrase est plus lisible, car il est explicitement marqué qu'on est en train de joindre deux tables, et avec quel critÚre.
Il y a plusieurs types de join
Ă notre disposition.
natural join
natural join
Il est possible de joindre deux tables en utilisant les attributs qui partagent le mĂȘme nom. Cela veut dire qu'on n'a pas besoin de la clause on
, parce que les critĂšres de jointure sont implicites.
Par exemple :
Ici, les attributs en commun entre les tables action
et action_customer
sont utilisés comme critÚres de jointure.
Mais attention ! Nous espérons que la jointure se fait via le lien établi via la clé étrangÚre (actionId
), mais ce n'est pas le cas avec natural join
. Il y a en effet, plusieurs colonnes avec le mĂȘme nom, notamment actionId
, createdAtUtc
, createdByUtc
, createdBy
, updatedBy
. Le natural join
va faire la jointure des lignes seulement si tous les attributs sont identiques entre les deux tables.
Prenons l'exemple de deux tables simples qui représente un pays et une équipe de football.
pays
id | pays | nom | langue |
---|---|---|---|
1 | FR | France | français |
2 | ZA | Afrique du Sud | anglais |
3 | UK | Grande Bretagne | anglais |
equipe
pays | equipe | langue |
---|---|---|
FR | Les bleus | français |
ZA | Bafana bafana | xhosa |
Et une requĂȘte de type natural join
:
Le résultat est :
id | pays | nom | langue | equipe |
---|---|---|---|---|
1 | FR | France | français | Les bleus |
On aurait attendu 2 lignes dans la jointure (pour les deux pays en commun, ZA
et FR
). En revanche, on voit que la requĂȘte nous retourne une seule ligne, car les attributs pays
et langue
sont utilisés dans la jointure.
Natural join, donc, n'est quasiment jamais utilisé, puisque le risque d'erreur est trop grand.
inner join
inner join
Un inner join
est typiquement le type de jointure que nous avons utilisés implicitement avec nos clauses from
et where
. Cette jointure nous retourne uniquement les lignes des 2 tables qui satisfont le critÚre précisé dans la condition de jointure.
Les lignes qui ne satisfont pas la condition sont exclues de la table gauche et la table droite de la jointure.
Reprenons notre exemple :
pays
id | pays | nom | langue |
---|---|---|---|
1 | FR | France | français |
2 | ZA | Afrique du Sud | anglais |
3 | UK | Grande Bretagne | anglais |
equipe
pays | equipe | langue |
---|---|---|
FR | Les bleus | français |
ZA | Bafana bafana | xhosa |
Une requĂȘte de type inner join
nous retourner de résultats plus cohérents :
Le résultat :
id | pays.pays | nom | pays.langue | equipe.pays | equipe | equipe.langue |
---|---|---|---|---|---|---|
1 | FR | France | français | FR | Les bleus | français |
2 | ZA | Afrique du Sud | anglais | ZA | Bafana bafana | xhosa |
Notez que le pays UK est exclu du résultat, parce qu'il n'y a pas de ligne correspondant (selon le critÚre) dans la table equipe
.
Vous avez dit de ne jamais utiliser le wildcard *
, pourquoi l'utiliser ici ?
C'est juste pour vous indiquer la différence entre natural join
et inner join
. Vous avez remarqué que natural join
nous a retourné une seule colonne pays
et une seule colonne langue
? C'est parce que la valeur est identique, donc pourquoi la répéter ?
Avec inner join
le critĂšre peut ĂȘtre plus complexe (la clause on
peut ĂȘtre un ensemble de conditions avec les opĂ©rateurs and
, or
et not
. L'équivalence n'est pas garantie). Donc, on est obligé d'afficher toutes les colonnes de la jointure dans le résultat.
Certains SGBDR permettent l'utilisation du join
(sans le mot inner
). Personnellement, je prĂ©fĂšre ĂȘtre explicite dans mes intentions, et je trouve qu'exprimer inner join
et plus parlant de ce qui va se passer dans la requĂȘte.
outer join
outer join
Il y a souvent la demande de joindre des tables et garder des lignes mĂȘme si une ligne correspondant ne se trouve pas dans l'autre table.
Pour continuer notre exemple, je veux voir la liste entiÚre de pays, malgré le fait qu'ils ont une équipe ou pas. J'utilise left outer join
Le résultat est :
id | pays.pays | nom | pays.langue | equipe.pays | equipe | equipe.langue |
---|---|---|---|---|---|---|
1 | FR | France | français | FR | Les bleus | français |
2 | ZA | Afrique du Sud | anglais | ZA | Bafana bafana | xhosa |
3 | UK | Grande Bretagne | anglais | null | null | null |
Avec le left outer join
, on garde toutes les lignes de la table gauche (avant l'opérateur left outer join
), malgré l'existence d'une ligne correspondante coté droite. On voit que pour le pays UK, il y a des valeurs null
Ă la place d'une Ă©quipe.
D'autres exemples des outer join
:
Je veux voir la liste d'articles dans mon catalogue qui avec, en option, le nombre de ventes de l'article (il faut afficher l'article mĂȘme s'il n'y a pas eu de vente)
Dans la base
saas
, je veux voir toutes les interventions et Ă©vĂ©nements. Il faut inclure mĂȘme les interventions qui n'ont pas d'Ă©vĂ©nement.
Il y a trois sortes de outer join
:
left outer join
: Conserver les lignes venant de la relation avant (ou sur la gauche) des motsleft outer join
, mĂȘme sâil nây a pas de correspondance dans lâautre relation. Attention : les lignes venant de lâautre relation (sur la droite) peuvent toujours ĂȘtre exclus !right outer join
: Conserver les lignes venant de la relation aprĂšs (ou sur la droite) des motsright outer join
, mĂȘme sâil nây a pas de correspondance dans lâautre relation. Attention : les lignes venant de la premiĂšre relation (sur la gauche) peuvent toujours ĂȘtre exclus !full outer join
: Conserver toutes les lignes des deux relations.
Exercices
Les exercices suivants sont basés sur la base de données SAKILA, une base de données de test fourni par MySQL.
Récupérez la base SAKILA ici.
Question 1
Utilisez lâopĂ©rateur join
afin dâafficher le nom, prĂ©nom, adresse et code postal de chaque membre de lâĂ©quipe (staff
).
Question 2
Utilisez join
afin de calculer le montant total encaissĂ© par chaque membre de lâĂ©quipe pendant le mois dâaoĂ»t 2005.
Question 3
Listez le nom et prénom de tous les clients (customer
). Si un client partage son nom avec un acteur, affichez le nom, prĂ©nom et ID de lâacteur aussi (sinon, affichez null
).
DerniĂšre mise Ă jour