IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

SQLpro

Explication d'un double left join ?

Noter ce billet
par , 24/10/2023 à 19h09 (2005 Affichages)
Citation Envoyé par SQLpro Voir le message
Soit les tables suivantes :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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....
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 :

Nom : 5.20 – Exemple d’arbre de jointure.jpg
Affichages : 109
Taille : 178,8 Ko

De manière plus détaillé voici ce que je montre dans mon livre sur SQL à paraître dans quelques semaines...


A +
Nom : SQL la synthese jointure annulation externe.jpg
Affichages : 104
Taille : 415,1 Ko

Envoyer le billet « Explication d'un double left join ? » dans le blog Viadeo Envoyer le billet « Explication d'un double left join ? » dans le blog Twitter Envoyer le billet « Explication d'un double left join ? » dans le blog Google Envoyer le billet « Explication d'un double left join ? » dans le blog Facebook Envoyer le billet « Explication d'un double left join ? » dans le blog Digg Envoyer le billet « Explication d'un double left join ? » dans le blog Delicious Envoyer le billet « Explication d'un double left join ? » dans le blog MySpace Envoyer le billet « Explication d'un double left join ? » dans le blog Yahoo

Commentaires