IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Choisir le bon type de jointure LEFT ou INNER?


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    616
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Luxembourg

    Informations forums :
    Inscription : Mars 2007
    Messages : 616
    Par défaut Choisir le bon type de jointure LEFT ou INNER?
    Bonjour,

    J'ai une question d'SQL. Je suis tombé sur un cas de figure similaire.
    Voici un exemple très simplifié schéma relationnel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     --------          ---------          -------
    |PERSONNE|        |COMPAGNIE|        |ADRESSE|
    |--------|0      1|---------|0      1|-------|
    |        |--------|         |--------|       |
    |        |        |         |        |       |
     --------          ---------          -------
    et je veux voir TOUTES les personnes avec la compagnie dans laquelle ils travaillent et l'adresse de la compagnie.

    Le problème est que lorsque je fais cette requête ca m'affiche les personnes uniquement qui tarvaillent
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT *
    FROM PERSONNE p
    	LEFT JOIN COMPAGNIE c
    		ON c.ID = p.C_ID
    	INNER JOIN ADRESSE a
    		ON a.ID = c.A_ID
    Lorsque je regarde le plan d'exécution je vois que le moteur fais un double INNER JOIN.
    Pourquoi?
    En fait pour afficher ce que je veux je dois faire un double LEFT JOIN, mais alors, dans ce cas là, je risque de voir une personne avec sa compagnie et sans adresse.
    Alors comment faire? Je dois absolument mettre une clause WHERE?

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 999
    Billets dans le blog
    6
    Par défaut
    C'est normal en faisant un INNER JOIN entre compagnie et adresse vous annulez l'outer join d'adresse ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Personne    Compagnie         Adresse 
     
    IPD         IDC    IDP        IDA     IDC
    --------    ---------------   ---------------
    1           10     1          Null               --> tuple éliminé puisque que INNER JOIN
    2           11     2          100     11
    3           Null              Null
    En principe dès que vous commencez une branche de jointure en OUTER il faut continuer toute la branche en outer !

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    616
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Luxembourg

    Informations forums :
    Inscription : Mars 2007
    Messages : 616
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    C'est normal en faisant un INNER JOIN entre compagnie et adresse vous annulez l'outer join d'adresse ...

    En principe dès que vous commencez une branche de jointure en OUTER il faut continuer toute la branche en outer !

    A +
    Vous voulez peut être dire "vous annulez l'outer join de compagnie" ?

    En prenant votre exemple je veux voir la ligne 2 et 3 mais pas la 1. Justement je pesais que si je faisais ce type de jointure (LEFT + INNER) ça m'éliminait le premier cas de figure, alors que ça m'affiche que le cas 2.

    Sinon je suis obligé de faire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT *
    FROM PERSONNE p
    LEFT JOIN (
    	SELECT * 
    	FROM COMPAGNIE c
    	INNER JOIN ADRESSE a
    		ON a.ID = c.A_ID
    ) c
    	ON c.ID = p.C_ID
    Je ne suis pas sûr que cette requête soit très performante.

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    En reprenant l'exemple de SQLPro je vous ai mis cinq cas de figure que vous pouvez obtenir, sans filtre, avec les jointures.
    On pense rarement à la dernière mais elle peut avoir son utilité.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    With Personne (IDP, IDC, Pnom) AS
    (
    select 1, 10  , 'PA' union all
    select 2, 11  , 'PB' union all
    select 3, null, 'PC'
    )
      ,  Compagnie (IDC, IDA, Cnom) AS
    (
    select 10, null, 'C1' union all
    select 11, 100 , 'C2'
    )
      ,  Adresse (IDA, Ville) AS
    (
    select 100, 'Paris'
    )
    SELECT 1 as idtyp, 'II' as typ, p.Pnom, c.Cnom, a.Ville
    FROM
        Personne as p
        INNER JOIN Compagnie as c
          ON c.IDC = p.IDC
        INNER JOIN Adresse as a
          ON a.IDA = c.IDA
    UNION ALL
    SELECT 2 as idtyp, 'LI' as typ, p.Pnom, c.Cnom, a.Ville
    FROM
        Personne as p
        LEFT OUTER JOIN Compagnie as c
          ON c.IDC = p.IDC
        INNER JOIN Adresse as a
          ON a.IDA = c.IDA
    UNION ALL
    SELECT 3 as idtyp, 'LL' as typ, p.Pnom, c.Cnom, a.Ville
    FROM
        Personne as p
        LEFT OUTER JOIN Compagnie as c
          ON c.IDC = p.IDC
        LEFT OUTER JOIN Adresse as a
          ON a.IDA = c.IDA
    UNION ALL
    SELECT 4 as idtyp, 'IL' as typ, p.Pnom, c.Cnom, a.Ville
    FROM
        Personne as p
        INNER JOIN Compagnie as c
          ON c.IDC = p.IDC
        LEFT OUTER JOIN Adresse as a
          ON a.IDA = c.IDA
    UNION ALL
    SELECT 5 as idtyp, 'L(I)' as typ, p.Pnom, c.Cnom, a.Ville
    FROM
        Personne as p
        LEFT OUTER JOIN Compagnie as c
        INNER JOIN Adresse as a
          ON a.IDA = c.IDA
          ON c.IDC = p.IDC
    ORDER BY idtyp asc;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    idtyp       typ  Pnom Cnom Ville
    ----------- ---- ---- ---- -----
    1           II   PB   C2   Paris
     
    2           LI   PB   C2   Paris
     
    3           LL   PA   C1   NULL
    3           LL   PB   C2   Paris
    3           LL   PC   NULL NULL
     
    4           IL   PA   C1   NULL
    4           IL   PB   C2   Paris
     
    5           L(I) PA   NULL NULL
    5           L(I) PB   C2   Paris
    5           L(I) PC   NULL NULL

  5. #5
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    616
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Luxembourg

    Informations forums :
    Inscription : Mars 2007
    Messages : 616
    Par défaut
    Citation Envoyé par Waldar Voir le message
    En reprenant l'exemple de SQLPro je vous ai mis cinq cas de figure que vous pouvez obtenir, sans filtre, avec les jointures.
    On pense rarement à la dernière mais elle peut avoir son utilité.
    En effet je ne comprends toujours pas comment elle peut fonctionner au niveau de syntaxe. J'ai une jointure sans clause ON et ensuite une autre avec 2 fois ON. D'ailleurs lorsqu'on remplace ce deuxième ON par AND, ça pose un problème.

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Il suffit d'imaginer avec le parenthésage implicite pour se rendre compte que la syntaxe est correcte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT 5 AS idtyp, 'L(I)' AS typ, p.Pnom, c.Cnom, a.Ville
    FROM
        Personne AS p
        LEFT OUTER JOIN (
        Compagnie AS c
        INNER JOIN Adresse AS a
          ON a.IDA = c.IDA)
          ON c.IDC = p.IDC
    ORDER BY idtyp ASC;

  7. #7
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    616
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Luxembourg

    Informations forums :
    Inscription : Mars 2007
    Messages : 616
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Il suffit d'imaginer avec le parenthésage implicite pour se rendre compte que la syntaxe est correcte :
    Je pesais qu'il fallait absolument faire un sous-SELECT:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT 5 AS idtyp, 'L(I)' AS typ, p.Pnom, c.Cnom, c.Ville
    FROM
        Personne AS p
        LEFT OUTER JOIN ( select c.*, a.Ville from 
    		Compagnie AS c 
        INNER JOIN Adresse AS a
          ON a.IDA = c.IDA)c
          ON c.IDC = p.IDC
    ORDER BY idtyp ASC;
    D'ailleurs y a -t-il une différence?
    Ce type de jointure a t il un nom particulier?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Choisir le bon type de "collection"
    Par bedomon dans le forum Collection et Stream
    Réponses: 8
    Dernier message: 06/07/2013, 13h06
  2. Choisir le bon type de projet
    Par lpouilly dans le forum Visual C++
    Réponses: 3
    Dernier message: 14/11/2011, 19h17
  3. PROC GLM : choisir le bon type SS en SAS?
    Par ganod dans le forum SAS STAT
    Réponses: 1
    Dernier message: 12/10/2009, 21h08
  4. Type de jointure et valeur NULL
    Par HULK dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 19/01/2005, 14h22
  5. [jointure] Petit problème sur le type de jointure...
    Par SteelBox dans le forum Langage SQL
    Réponses: 13
    Dernier message: 13/02/2004, 18h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo