Soit les tables suivantes :
1 2 3 4 5 6 7
| CREATE TABLE T_PERSONNE
(PRS_ID INT PRIMARY KEY,
PRS_NOM VARCHAR(16) NOT NULL);
INSERT INTO T_PERSONNE VALUES
(1, 'DUPONT'),
(2, 'MARTIN'),
(3, 'SMITH'); |
Table des personnes
1 2 3 4 5 6 7 8
| CREATE TABLE T_DNS
(DNS_ID INT PRIMARY KEY,
DNS_NAME VARCHAR(128) NOT NULL);
INSERT INTO T_DNS VALUES
(99, 'gmail.com'),
(98, 'outlook.fr'),
(97, 'free.fr'),
(96, 'orange.fr'); |
Table des DNS
1 2 3 4 5 6 7 8 9
| CREATE TABLE T_EMAIL
(EML_ID INT PRIMARY KEY,
PRS_ID INT NOT NULL REFERENCES T_PERSONNE (PRS_ID),
DNS_ID INT NOT NULL REFERENCES T_DNS (DNS_ID),
EML_USER VARCHAR(128) NOT NULL);
INSERT INTO T_EMAIL VALUES
(33, 1, 99, 'paul.dupont356'),
(35, 1, 98, 'pdupont45'),
(37, 3, 99, 'smith-et-wesson'); |
Tables des emails liés aux deux autres : personnes et DNS (un email est composé d'un nom d'utilisateur et d'un nom de DNS séparé par le caractères "@" : arobe)
La requête suivante présentes les utilisateurs avec leurs emails :
1 2 3 4
| SELECT P.*, CONCAT(EML_USER, '@', DNS_NAME) AS EMAIL
FROM T_PERSONNE AS P
INNER JOIN T_EMAIL AS E ON P.PRS_ID = E.PRS_ID
INNER JOIN T_DNS AS D ON E.DNS_ID = D.DNS_ID; |
1 2 3 4 5
| PRS_ID PRS_NOM EMAIL
----------- ---------------- -----------------------------
1 DUPONT paul.dupont356@gmail.com
1 DUPONT pdupont45@outlook.fr
3 SMITH smith-et-wesson@gmail.com |
Les jointures étant internes, la personne 2 (MARTIN) n'y figure pas...
Rectifions avec des jointures externes :
1 2 3 4
| SELECT P.*, CONCAT(EML_USER, '@', DNS_NAME) AS EMAIL
FROM T_PERSONNE AS P
LEFT OUTER JOIN T_EMAIL AS E ON P.PRS_ID = E.PRS_ID
LEFT OUTER JOIN T_DNS AS D ON E.DNS_ID = D.DNS_ID; |
1 2 3 4 5 6
| PRS_ID PRS_NOM EMAIL
----------- ---------------- ---------------------------
1 DUPONT paul.dupont356@gmail.com
1 DUPONT pdupont45@outlook.fr
2 MARTIN
3 SMITH smith-et-wesson@gmail.com |
La personne 2 (MARTIN) y figure mais sans préciser son email...
Qu'en est-il si nous faisons une jointure externe suivie d'une jointure interne ?
Après tout le DNS est obligatoire (NOT NULL) dans la table des EMAILs....
1 2 3 4
| SELECT P.*, CONCAT(EML_USER, '@', DNS_NAME) AS EMAIL
FROM T_PERSONNE AS P
LEFT OUTER JOIN T_EMAIL AS E ON P.PRS_ID = E.PRS_ID
INNER JOIN T_DNS AS D ON E.DNS_ID = D.DNS_ID; |
1 2 3 4 5
| PRS_ID PRS_NOM EMAIL
----------- ---------------- -----------------------------
1 DUPONT paul.dupont356@gmail.com
1 DUPONT pdupont45@outlook.fr
3 SMITH smith-et-wesson@gmail.com |
À nouveau, la personne 2 (MARTIN) n'y figure plus... Quel est ce mystère ???
Vous allez commencer à comprendre si j'indente ma requête comme ceci :
1 2 3 4
| SELECT P.*, CONCAT(EML_USER, '@', DNS_NAME) AS EMAIL
FROM T_PERSONNE AS P
LEFT OUTER JOIN T_EMAIL AS E ON P.PRS_ID = E.PRS_ID
INNER JOIN T_DNS AS D ON E.DNS_ID = D.DNS_ID; |
La jointure se fait entre personnes et email puis entre email et dns... Dès lors si une personne n'a pas d'email... Elle n'a pas non plus de DNS, puisque le DNS_ID figure dans la table des emails !
Avec toutes les colonnes la situation est plus évidente :
1 2 3 4 5 6
| PRS_ID PRS_NOM EML_ID PRS_ID DNS_ID EML_USER DNS_ID DNS_NAME
----------- ---------------- ----------- ----------- ----------- ------------------- ----------- -------------
1 DUPONT 33 1 99 paul.dupont356 99 gmail.com
1 DUPONT 35 1 98 pdupont45 98 outlook.fr
2 MARTIN 37 2 99 smith-et-wesson 99 gmail.com
3 SMITH NULL NULL NULL NULL NULL NULL |
En bleu la partie de la table des EMAILs qui est vide et en rouge la partie des DNS qui est aussi vide car il n'y a pas d'email...
La clause FROM présente en fait une arborescence des jointure. La table citée derrière la clause FROM est la table racine de l'arbre de jointure. Les JOINs successifs dessinent des branches successives plus ou moins profondes. Voici un exemple qui présente mieux les différentes branches de l'arbre de jointure :
De manière plus détaillé voici ce que je montre dans mon livre sur SQL à paraître dans quelques semaines...
A +
