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.
select
a.name as Action,
c.name as Customer
from
action as a,
customer as c,
action_customer as ac
where
a.actionId = ac.actionId and
ac.customerId = c.customerId;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 :
select a.name as Action, c.name as Customer
from
action a
inner join
action_customer ac on a.actionId = ac.actionId
inner join
customer c on ac.customerId = c.customerId;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 joinIl 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 :
select a.name, ac.amount
from action a
natural join action_customer ac;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
1
FR
France
français
2
ZA
Afrique du Sud
anglais
3
UK
Grande Bretagne
anglais
equipe
FR
Les bleus
français
ZA
Bafana bafana
xhosa
Et une requĂȘte de type natural join :
select *
from pays
natural join equipe;Le résultat est :
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 joinUn 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
1
FR
France
français
2
ZA
Afrique du Sud
anglais
3
UK
Grande Bretagne
anglais
equipe
FR
Les bleus
français
ZA
Bafana bafana
xhosa
Une requĂȘte de type inner join nous retourner de rĂ©sultats plus cohĂ©rents :
select *
from pays
inner join equipe on pays.pays = equipe.pays;Le résultat :
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 joinIl 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
select *
from pays
left outer join equipe on pays.pays = equipe.pays;Le résultat est :
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).
Mis Ă jour