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

Langage SQL Discussion :

Problème de jointure externe sur trois tables


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2012
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 37
    Par défaut Problème de jointure externe sur trois tables
    Bonjour,

    je perds beaucoup de temps sur une évolution

    pour des raisons de confidentialités je simplifie le sujet.

    Voici ma demande, j'ai 3 tables :
    - CLIENT : les clients
    - TYPE_CLIENT : le type de client
    - TYPE_LIBELLE : la traduction du libellé en fonction du code langue
    - LANGUES : la table des langues (que je ne vais pas créer)

    la table CLIENT a une clé étrangère qui pointe sur la clé primaire de la table TYPE_CLIENT.
    la table TYPE_CLIENT
    la table TYPE_LIBELLE est une table d'association entre LANGUES et TYPE_CLIENT et contient le libellé dans la langue choisie.
    Il y une clé étragère qui pointe sur un champ de la table TYPE_LIBELLE + LANGUE (que je ne vais pas décrire)

    Je dois récupérer des champs de la tables CLIENT (peu importe des champs) + le libellé de la table TYPE_LIBELLE.
    La nouveauté c'est que le champs qui relie la table CLIENT à TYPE_CLIENT peut être NULL et compléter plus tard. Et là tout devient compliqué avec les jointures

    voici les tables (je rappelle que pour des raisons de confidentialités j'ai pris un exemple aléatoire, donc ne pas me troller violamment que le choix des noms de champs sont pourris ou que je devrais faire des tables autrement car ce n'est pas le sujet de ma demande... ^^)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    CREATE TABLE AAA_TYPE_CLIENT (
          idTypeClient int not null,
          constraint idTypeClient_pk primary key (idTypeClient),
          )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    CREATE TABLE AAA_TYPE_LIBELLE (
          id int not null,
          idLangue int not null,
          idTypeClient int not null,
          libelle nvarchar(255) not null,
          constraint id_pk primary key (id),
          -- je ne ferai pas la FK ni les autres règles de contraintes d'intégrités qui va sur langue dans mon exemple
          constraint idTypeClient_fk foreign key (idTypeClient) references AAA_TYPE_CLIENT(idTypeClient)
          )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    CREATE TABLE AAA_CLIENT (
          idClient int not null,
          idTypeClient int NULL,
          constraint client_pk primary key (idClient),
          constraint idTypeClient2_fk foreign key (idTypeClient) references AAA_TYPE_CLIENT(idTypeClient)
          )

    // les insert

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    insert into AAA_TYPE_CLIENT values (1);
     
    insert into AAA_CLIENT values (1, 1);
    insert into AAA_CLIENT values (2, 1);
    insert into AAA_CLIENT values (3, 1);
    insert into AAA_CLIENT values (4, null);
     
    insert into AAA_TYPE_LIBELLE values (1, 1, 1, 'azerty');
    // mon ancienne requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT D.idClient, L.libelle
    FROM AAA_CLIENT D INNER JOIN AAA_TYPE_CLIENT T on D.idTypeClient = T.idTypeClient
    INNER JOIN AAA_TYPE_LIBELLE L on T.idTypeClient = L.idTypeClient 
    WHERE L.idLangue = 1
    il retourne 3 résultats mais il me faut la ligne manquante avec pour valeur null ou blanc car cette dernière à une clé étangère à null.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT D.idClient
    FROM AAA_CLIENT D LEFT OUTER JOIN AAA_TYPE_CLIENT T on D.idTypeClient = T.idTypeClient
    j'ai mes 4 résultat mais sans le champs libellé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT D.idClient
    FROM AAA_CLIENT D LEFT OUTER JOIN AAA_TYPE_CLIENT T on D.idTypeClient = T.idTypeClient
    INNER JOIN AAA_TYPE_LIBELLE L on T.idTypeClient = L.idTypeClient 
    WHERE L.idLangue = 1
    toujours 3 champs

    Pouvez-vous m'aider svp pour avoir les 4 lignes?

    ps :

    ça aussi ça marche pour 4 lignes sans le champs "libelle"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT D.idClient
    FROM AAA_CLIENT D LEFT OUTER JOIN (select T.idTypeClient from AAA_TYPE_CLIENT T INNER JOIN AAA_TYPE_LIBELLE L on T.idTypeClient = L.idTypeClient 
    WHERE L.idLangue = 1) JOINTURE
    ON D.idTypeClient = JOINTURE.idTypeClient

  2. #2
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Par défaut
    bonjour,

    votre dernière requete :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT D.idClient
    FROM AAA_CLIENT D LEFT OUTER JOIN (SELECT T.idTypeClient FROM AAA_TYPE_CLIENT T INNER JOIN AAA_TYPE_LIBELLE L ON T.idTypeClient = L.idTypeClient 
    WHERE L.idLangue = 1) JOINTURE
    ON D.idTypeClient = JOINTURE.idTypeClient
    est bonne.

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2012
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 37
    Par défaut
    Citation Envoyé par punkoff Voir le message
    bonjour,

    votre dernière requete :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT D.idClient
    FROM AAA_CLIENT D LEFT OUTER JOIN (SELECT T.idTypeClient FROM AAA_TYPE_CLIENT T INNER JOIN AAA_TYPE_LIBELLE L ON T.idTypeClient = L.idTypeClient 
    WHERE L.idLangue = 1) JOINTURE
    ON D.idTypeClient = JOINTURE.idTypeClient
    est bonne.


    en faite je voulais dire que ça retourne 4 lignes mais je n'ai affiché pas le champs "libelle". donc le but n'est pas atteint.

    j'ai trouvé une autre requête qui cette fois ci me retourne bien le résultat attendu : 4 lignes avec le champs "libelle" rempli ou null

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    SELECT D.idClient, 
    (select L.libelle from AAA_TYPE_LIBELLE L INNER JOIN AAA_TYPE_CLIENT T ON L.idTypeClient = T.idTypeClient where T.idTypeClient = D.idTypeClient and L.idLangue = 1)
    FROM AAA_CLIENT D
    mais c'est moins pro

  4. #4
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 953
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 953
    Par défaut
    Citation Envoyé par arnovodao Voir le message
    j'ai trouvé une autre requête qui cette fois ci me retourne bien le résultat attendu : 4 lignes avec le champs "libelle" rempli ou null
    ...
    mais c'est moins pro
    C'est une requête corrélée, ça n'est pas moins pro, c'est juste qu'en fonction des besoins c'est plus ou moins pertinent/performant.
    Pour ce besoin, ça ne semble pas pertinent, il suffit de rajouter le libellé dans la sous-requête JOINTURE et de le sélectionner tout simplement.

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Par défaut
    Bah faut juste rajouter le libellé dans la sous-requete :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT D.idClient, JOINTURE.libelle
    FROM AAA_CLIENT D 
    LEFT OUTER JOIN (
     SELECT T.idTypeClient, L.libelle
     FROM AAA_TYPE_CLIENT T 
     INNER JOIN AAA_TYPE_LIBELLE L ON T.idTypeClient = L.idTypeClient 
     WHERE L.idLangue = 1) JOINTURE
    ON D.idTypeClient = JOINTURE.idTypeClient

    Une autre solution est de ne passer que par des jointures externes, à voir selon le SGBD, la meilleur écriture ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT D.idClient, L.libelle
    FROM AAA_CLIENT D 
    LEFT OUTER JOIN AAA_TYPE_CLIENT T ON D.idTypeClient = T.idTypeClient 
    LEFT OUTER JOIN AAA_TYPE_LIBELLE L ON T.idTypeClient = L.idTypeClient and L.idLangue = 1

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2012
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 37
    Par défaut
    Une autre solution est de ne passer que par des jointures externes, à voir selon le SGBD, la meilleur écriture ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT D.idClient, L.libelle
    FROM AAA_CLIENT D 
    LEFT OUTER JOIN AAA_TYPE_CLIENT T ON D.idTypeClient = T.idTypeClient 
    LEFT OUTER JOIN AAA_TYPE_LIBELLE L ON T.idTypeClient = L.idTypeClient and L.idLangue = 1

    Excellent. En fait cette requête c'est exactement celle que j'avais commencé par écrire mais j'avais mis un "WHERE L.idLangue = 1" et ça me retournait que les lignes dont la jointure était OK. Par contre en remplaçant par "and L.idLangue = 1", j'ai toutes les lignes.

    Je ne comprends pas vraiment cette différence de comportement entre le AND et WHERE.

    Tout mon problème venait de là.

    Merci beaucoup!

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

Discussions similaires

  1. jointure externe sur 2 tables
    Par serna dans le forum Débuter
    Réponses: 11
    Dernier message: 11/03/2010, 09h43
  2. Jointure externe sur 3 tables
    Par Gobouz dans le forum Requêtes
    Réponses: 3
    Dernier message: 21/12/2009, 13h48
  3. jointure externe sur 2 tables
    Par rupteur dans le forum Langage SQL
    Réponses: 3
    Dernier message: 25/03/2009, 14h03
  4. Jointures externes sur une table de jointure
    Par mart1 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 10/10/2006, 01h33
  5. Jointure externe sur 2 tables
    Par Danae dans le forum Langage SQL
    Réponses: 11
    Dernier message: 19/07/2005, 15h37

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