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 :

Microsoft Access - Left/Right Outer Join


Sujet :

Langage SQL

  1. #1
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut Microsoft Access - Left/Right Outer Join
    Bonjour à tous,

    J'essais de faire un Right Outer Join mais ça ne fonctionne pas bien à mon avis avec MS Access

    (Voir l'image en pièce jointe pour mes deux tables et leur relations.)

    C'est très simple comme exemple mais ça suffira :
    La table Jours contient tous les jours de la semaine.
    La table ClientsJours contient tous les jours qu'un client peut posséder.

    Voilà ce que contient ma table Jours :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ID          NOM
    1         Dimanche
    2         Lundi
    3         Mardi
    4         Mercredi
    5         Jeudi
    6         Vendredi
    7         Samedi
    Et ma table ClientsJours :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ClientID       JourID
       1             1
       1             4 
       1             5
       2             1
       3             6
    J'aimerais pour un client ayant un ID précis, récupérer TOUS les lignes étant dans la table Jours et ainsi qu'un champs addtionnel avec un 0 ou un 1 pour dire si il le client le possède.

    Voilà ce à quoi ça devrait ressembler pour le client #1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      Jours     Sélectionner
    Dimanche         1
    Lundi            0 
    Mardi            0
    Mercredi         1
    Jeudi            1
    Vendredi         0
    Samedi           0
    Voilà ce que j'ai comme requête jusqu'ici. Faut dire que j'ai l'habitude de faire des LEFT OUTER JOIN avec MySQL et MS SQL et ça fonctionne très bien !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM Jours RIGHT OUTER JOIN 
            ClientsJours ON Jours.ID = ClientsJours.JourID
    WHERE ClientsJours.ClientID = 1;
    Mais ça ne fonctionne pas ! Il me renvoit seulement ceux qui sont présent dans la table ClientJours. Moi je veux TOUS ceux de la table Jours...

    Bref, merci d'avance pour votre aide
    Images attachées Images attachées  
      0  0

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Pour avoir tous les jours même s'il n'y a pas de client pour ce jour, c'est un LEFT JOIN qu'il faut que tu fasses si tu veux mettre ta table des jours en premier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Jour LEFT JOIN ClientJour
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClientJour RIGHT JOIN Jour
      0  0

  3. #3
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut
    Citation Envoyé par vmolines Voir le message
    Pour avoir tous les jours même s'il n'y a pas de client pour ce jour, c'est un LEFT JOIN qu'il faut que tu fasses si tu veux mettre ta table des jours en premier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Jour LEFT JOIN ClientJour
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClientJour RIGHT JOIN Jour
    J'ai déjà essayé :

    Jour LEFT JOIN ClientJour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM Jours LEFT  JOIN 
            ClientsJours ON Jours.ID = ClientsJours.JourID
    WHERE ClientsJours.ClientID=1;
    Jour LEFT JOIN ClientJour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM ClientsJours RIGHT JOIN 
             Jours ON ClientsJours.JourID = Jours.ID
    WHERE ClientsJours.ClientID=1;
    Dans les deux cas ça donne le même résultat, c'est-à-dire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Nom            Sélectionné
    Dimanche           1
    Mercredi           1
    Jeudi              1
    Et ce n'est pas du tout le résultat attendu !
    En pièce jointe, j'ai mis le fichier BD Access, esssayer et vous verrez
    Fichiers attachés Fichiers attachés
      0  0

  4. #4
    say
    say est déconnecté
    Membre éprouvé
    Avatar de say
    Profil pro
    Inscrit en
    Août 2002
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 1 176
    Points : 1 258
    Points
    1 258
    Par défaut
    je pense que le problème vient de là:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE ClientsJours.ClientID=1;
    au vu de ce que tu veux avoir, la "bonne requête est avec le LEFT :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM Jours LEFT  JOIN 
            ClientsJours ON Jours.ID = ClientsJours.JourID
    WHERE ClientsJours.ClientID=1;
    sauf que tu as une clause WHERE qui va à l'encontre de ton LEFT. appliquer une clause where sur la table de "droite" (clientsjours) revient à faire un INNER JOIN.

    essaies :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM Jours LEFT  JOIN 
            ClientsJours ON Jours.ID = ClientsJours.JourID
    WHERE ClientsJours.ClientID=1 OR ClientsJours.ClientID IS NULL;
    ou (mais je suis pas sur que ça passe sous access) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM Jours LEFT  JOIN 
            ClientsJours ON Jours.ID = ClientsJours.JourID AND ClientsJours.ClientID=1;
      0  0

  5. #5
    Membre confirmé Avatar de chrifo
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    444
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 444
    Points : 481
    Points
    481
    Par défaut
    Bonjour,

    Citation Envoyé par Erakis Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WHERE ClientsJours.ClientID=1;
    Cette clause vous enlève le côté "externe" de la jointure, essayez :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM Jours LEFT  JOIN 
            (select * from ClientsJours where ClientID = 1) CJ ON Jours.ID = CJ.JourID;
    ou même :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM Jours LEFT  JOIN 
            ClientsJours ON Jours.ID = ClientsJours.JourID and ClientsJours.ClientID=1;
    Coiffé au poteau
    La solution de say me semble également correcte
      0  0

  6. #6
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut
    Merci à tous pour votre aide, c'est apprécié

    Pour cette requête, cela fonctionne très bien. Juste qu'elle n'est pas supportée dans le designer mais ça, on s'en balance !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné
    FROM Jours LEFT JOIN 
            ClientsJours ON ((Jours.ID = ClientsJours.JourID)  AND (ClientsJours.ClientID = 1));
    Et celle-la aussi fonctionne très bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT Jours.Nom, 
                 IIf(IsNull([JourID]),0,1) AS Sélectionné
    FROM Jours LEFT JOIN ClientsJours ON Jours.ID = ClientsJours.JourID
    WHERE ClientsJours.ClientID = 1 OR IsNull(ClientsJours.ClientID);
    Cependant, par curiosité, je me demande bien POURQUOI ma première requête fonctionne TRÈS bien sur MySQL ou MS SQL ???
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT Jours.Nom, 
               IIf(IsNull([JourID]),0,1) AS Sélectionné 
    FROM Jours RIGHT OUTER JOIN 
            ClientsJours ON Jours.ID = ClientsJours.JourID
    WHERE ClientsJours.ClientID = 1;
    Cela fait 5 ans que je travail avec ces deux SGBD et je n'ai jamais eu ce genre de problème de logique...
      0  0

  7. #7
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Salut !

    Sans vouloir être contrariant, ça ne marche pas non plus sous SQL Serveur...
    (du moins sous SQL Serveur 2005)
    La condition sur le jour dans la clause WHERE filtre le résultat de la jointure externe. Et dans ce cas, ça nettoie toutes les lignes "externes"...
      0  0

  8. #8
    say
    say est déconnecté
    Membre éprouvé
    Avatar de say
    Profil pro
    Inscrit en
    Août 2002
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 1 176
    Points : 1 258
    Points
    1 258
    Par défaut
    je suis très très surpris que vous n'ayez jamais rencontré ça...ce n'est pas un genre de logique mais le principe des jointures externes...difficile d'imaginer que vous ayez les bons résultats...mais ça doit être lié au SGBD..surprenant qd même
      0  0

  9. #9
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut
    Désolé, j'ai dit que sur Microsoft SQL Express ça fonctionnait bien mais je ne l'ai pas testé. C'est mon erreur J'ai présumé que cela fonctionnerait en me basant sur la théorie...

    Cependant, avec MySQL je peux vous CONFIRMER que cela fonctionne très bien car j'ai l'habitude d'utiliser des OUTER JOIN presqu'à tous les jours

    À présent, jetez un coup d'oeil sur ce lien : Wikipedia Inner Join. En se basant sur ce texte, Microsft ne s'en tient pas aux règles ! Et ça me surprend pas LOL. Juste à regarder IE !
      0  0

  10. #10
    Membre confirmé Avatar de chrifo
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    444
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 444
    Points : 481
    Points
    481
    Par défaut
    Si si, microsoft comme les autres s'en tient aux règles.

    Sans présumer du plan d'exécution, on peut expliquer ça en raisonnant simplement sur les ensembles résultats :
    - l'ensemble ramené par la jointure externe est correct
    - la clause where fait ensuite le filtre demandé sur cet ensemble, ne ramenant que les ClientID = 1, donc éliminant entre autres tous les null

    Le résultat ramené par MySQL lors de vos tests est à mon sens complètement erroné
      0  0

  11. #11
    say
    say est déconnecté
    Membre éprouvé
    Avatar de say
    Profil pro
    Inscrit en
    Août 2002
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 1 176
    Points : 1 258
    Points
    1 258
    Par défaut
    Je pense qu'on est tous d'accord pour dire que l'ordre de traitement est le suivant (grossièrement) :

    1/ la jointure
    2/ le where qui applique un filtre sur la jointure.


    si vous voulez débattre :
    http://www.developpez.net/forums/sho...d.php?t=522319
      0  0

Discussion fermée
Cette discussion est résolue.

Discussions similaires

  1. fonctionnement du RIGHT OUTER JOIN hibernate
    Par Pinkwyzard dans le forum Hibernate
    Réponses: 0
    Dernier message: 26/05/2009, 12h20
  2. [SQL2K5][MDX] Left ou Right Outer Join en MDX
    Par Jinroh77 dans le forum SSAS
    Réponses: 8
    Dernier message: 27/08/2008, 09h49
  3. [CRXI] Problème avec Left/Right Outer
    Par Lo² dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 26/07/2007, 11h15
  4. Right Outer Join
    Par RodEpsi dans le forum Langage SQL
    Réponses: 10
    Dernier message: 15/03/2007, 18h30
  5. [migration] right outer join (+) vers SQL Standard
    Par Kahiros dans le forum Oracle
    Réponses: 7
    Dernier message: 02/01/2006, 09h41

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