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 :

Jointures qui joignent mal


Sujet :

Langage SQL

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 26
    Points : 16
    Points
    16
    Par défaut Jointures qui joignent mal
    Bonjour !

    Arghl ! Encore une galère de jointures...

    Donc voilà, j'ai deux tables.

    La première PATHOSLIST donne le nom de pathologies :
    ID | INTITULE
    1 | Maux de tête
    2 | Douleur musculaire

    La seconde, OBSPATHOS, relie des observations entre elles :
    ID | IDPATHOS | IDOBS | IDPATIENT
    161| 2 | 60 | 33
    162| 2 | 59 | 33
    163| 1 | 60 | 33

    J'essaie de générer:
    1. la liste de toutes les pathologies
    2. Ensuite, pour chaque pathologie et pour un couple idpatient/idobs donné, si cette pathologie est référencée (information ou null)

    Ceci me permettra de générer une liste de cases à cocher, et de les cocher si la pathologie est référencée pour l'observation donnée.

    J'ai donc besoin de générer un résultat du type suivant, par exemple pour idobs=59 et idpatient=33 :

    PATHOSLIST.ID | INTITULE | OBSPATHOS.ID | IDPATHOS | IDOBS | IDPATIENT
    1| Maux de tête | null | null | null | null
    2 | Douleur musculaire | 162 | 2 | 59 | 33

    Voici ma requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT pathoslist.id AS pathoslistid, intitule, 
      obspathos.id AS obspathosid, 
      idpathos, idobs, idpatient 
    FROM pathoslist 
    LEFT JOIN obspathos ON pathoslist.id=obspathos.idpathos 
    WHERE (idobs='59' AND idpatient='33') 
      OR (idobs IS NULL AND idpatient IS NULL) 
    ORDER BY intitule
    Je n'obtiens que la seconde ligne des résultats escomptés.
    En effet, si l'on exclut la sélection par WHERE, pour afficher tous les résultats de la jointure, les maux de tête ne sont pas NULL, puisque existant à l'enregistrement 163.
    En appliquant ma sélection par WHERE, je n'obtiens plus que le résultat 161, et je perds le résultat souhaité des maux de tête non observés chez ce patient (NULL)

    Que de maux de tête...

    Auriez-vous une petite suggestion pour moi ?

    En vous remerciant....

  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 902
    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 902
    Points : 51 646
    Points
    51 646
    Billets dans le blog
    6
    Par défaut
    Il faut faire le produit cartésien à l'aide d'un CROSS JOIN.

    A +

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 26
    Points : 16
    Points
    16
    Par défaut
    Merci pour ta réponse.
    (et merci à CinePhil pour la meilleure lisibilité de la requête)

    En remplaçant le LEFT JOIN par un CROSS JOIN, j'obtiens le même résultat semble-t-il...

    Comment pourrais-je forcer l'apparition des NULL dans mes résultats ?

  4. #4
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 109
    Points : 28 437
    Points
    28 437
    Par défaut
    Je n'ai pas tout compris, mais est-ce que cette requête ne retournerait pas ce que tu attends
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT pathoslist.id AS pathoslistid, intitule, 
      obspathos.id AS obspathosid, 
      idpathos, idobs, idpatient 
    FROM pathoslist 
    LEFT JOIN obspathos ON pathoslist.id=obspathos.idpathos 
      AND idobs='59' AND idpatient='33'
    ORDER BY intitule

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 902
    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 902
    Points : 51 646
    Points
    51 646
    Billets dans le blog
    6
    Par défaut
    Merci de respecter les règles du forum en donnant le code DDL (CREATE TABLE) ainsi que des INSERT INTO afin de nous faciliter la tâche !
    Enfin donnez nous un exemple sous forme de table de ce que vous voulez voir apparaître comme réponse

    En faisant cela vous respecterez les règles de postage visible ici :
    http://www.developpez.net/forums/a69...gage-sql-lire/

    Voici une solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CREATE TABLE PATHOSLIST (ID INT, INTITULE VARCHAR(24))
    INSERT INTO PATHOSLIST 
    VALUES (1, 'Maux de tête'), (2, 'Douleur musculaire')
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CREATE TABLE OBSPATHOS (ID INT, IDPATHOS INT, IDOBS INT, IDPATIENT INT)
    INSERT INTO OBSPATHOS VALUES (161, 2 , 60 , 33),
    (162, 2 , 59 , 33),
    (163, 1 , 60 , 33)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT *
    FROM   PATHOSLIST AS P
           CROSS JOIN (SELECT DISTINCT IDPATIENT FROM OBSPATHOS) AS C
           LEFT OUTER JOIN OBSPATHOS AS O
                ON P.ID = O.IDPATHOS
                AND C.IDPATIENT = O.IDPATIENT
                AND IDOBS = 59 
                AND O.IDPATIENT = 33
    QUi donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ID          INTITULE                 IDPATIENT   ID          IDPATHOS    IDOBS       IDPATIENT
    ----------- ------------------------ ----------- ----------- ----------- ----------- -----------
    1           Maux de tête             33          NULL        NULL        NULL        NULL
    2           Douleur musculaire       33          162         2           59          33
    Je note des erreurs de conception qui vous empêche de comprendre ce que vous faites :

    1) dans une base de données, les colonnes porteuse de la même info doivent avoir le même nom (norme AFNOR et simple bon sens !)
    Ainsi ID dans PATHOSLIST et dans OSPATHOS contrevienne à cela; Voila une des difficultés majeures pour vous : concevoir des requêtes avec des noms de colonnes qui sont différent pour une même jointure ! D'où un mélange catastrophique ! jointure avec "CHAT = BANANE"

    2) des nombres ne sont pas des chaines de caractères. Il ne faut donc pas les entourer d'apostrophe !

    A +

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 26
    Points : 16
    Points
    16
    Par défaut
    Merci à tous deux pour vos réponses.

    J'ai d'abord testé la solution de al1_124 qui correspond exactement à ce que je cherchais.
    Il fallait donc placer les critères directement dans les critères de jointure, et non dans le Where, qui semble être pris en compte dans un second temps.

    J'ai également bien noté les remarques de SQLpro (qui porte bien son nom ) Donc plus de clarté et de cohérence dans la dénomination de mes champs, et dans la manière d'afficher mon code sur le forum...
    Par contre, je me suis creusé la tête à comprendre les différences entre les deux solutions, à savoir les deux codes suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FROM pathoslist LEFT JOIN obspathos
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FROM   PATHOSLIST
    CROSS JOIN (SELECT DISTINCT IDPATIENT FROM OBSPATHOS)
    Si j'ai bien compris, je crois que cela revient au même dans mon cas particulier.

    En tout cas merci !

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

Discussions similaires

  1. un DELETE qui fonctionne mal
    Par HULK dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 06/02/2006, 18h59
  2. [SQL] une requete qui fait mal a la tete
    Par MailOut dans le forum Langage SQL
    Réponses: 7
    Dernier message: 07/02/2005, 16h22
  3. [SQL] Requête à jointure qui ne fonctionne pas
    Par Bensor dans le forum Langage SQL
    Réponses: 2
    Dernier message: 09/12/2004, 16h10

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