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 :

Auto jointure (externe) sur clés etrangères


Sujet :

Langage SQL

  1. #1
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut Auto jointure (externe) sur clés etrangères
    Bonjour,
    je me retrouve confronté à un problème sur des jointures externe portant sur la meme table.
    EX: 2 tables
    Historique( date, refTache, valeur,)
    Tache(idTache, libelle )

    je peux avoir
    Historique (1-1-2006, 0, 1)
    Historique (1-1-2006, 0, 2)
    Historique (5-5-2008, 5, 1)
    Historique (5-5-2008, 2, 2)
    Historique (5-5-2008, 1, 3)


    et 3 tuples pour la table Tache


    Je voudrais les valeurs pour chaque tache pour les historiques à 2 dates différentes

    Par exemple avec la requete suivante:

    select t.libelle, histo2.valeur, histo1.valeur
    from
    Tache t
    inner join Historique histo2 on histo2.reftTache = t.idTache
    left outer join Historique histo1 on histo1.refTache = histo2.refTache
    where histo1.date = 'yyyyy'
    AND histo2.date = 'xxxxx'
    group by histo2.refTache;


    je voudrais donc obtenir pour toutes les taches qui sont présentes dasn histo2, la valeur dans histo1 ou NULL si elle n'existe pas


    Or ca ne marche pas et j'obtient que les enregisterment communs (tache 1 & 2, mais pas la 3, comme si le left join se comportait en inner join).

    En fait ce probleme est recurant sur plusieurs requetes que j'ecris en ce moment...
    Je pense que ca vient d'une mauvaise comprehension des jointures, si pouvez vous pouviez m'aider...

    merci d'avance

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mars 2006
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Mars 2006
    Messages : 400
    Points : 562
    Points
    562
    Par défaut
    je voudrais les valeurs pour chaque tache pour les historiques à 2 dates différentes
    Souhaites-tu obtenir les 2 historiques les plus récents ?


    Pour obtenir les historiques correspondant à une date 'yyyyy' et 'xxxxxx', essaye :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT *
    FROM Tache
    LEFT JOIN Historique ON reftTache=idTache
    WHERE date = 'yyyyy' OR date = 'xxxxx'
    ORDER BY idTache
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select t.libelle, histo2.valeur, histo1.valeur
    from
    Tache t
    inner join Historique histo2 on histo2.reftTache = t.idTache
    left outer join Historique histo1 on histo1.refTache = histo2.refTache
    where histo1.date = 'yyyyy'
    AND histo2.date = 'xxxxx'
    group by histo2.refache;
    Cette requête sélectionne les tâches (SELECT * FROM Tache).
    A ces tâches sont liées tous les historiques respectifs (histo2).
    A ces historiques sont liés tous les historiques (histo1) correspondants à la même tâche.
    Seuls les histo2 où date="xxxxxx" et les histo1 où date ="yyyyy" sont affichés.
    Avec le GROUP BY, les résultats sont regroupés par tâche. Tu n'obtiens donc qu'un seul résultat par tâche.

  3. #3
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    en fait j'ai besoin de mettre en correspondance pour chaque tache, 2 historiques, sachant que dans l'historique le + récent peut apparaitre un tache qui n'existait pas dans l'autre historique
    Le groupe by tache est inutile en fait, car la clé primaire de histo est composée de la date ET de la tache)

    En fait, c'est comme si je voulais faire une union de ta requete precedante:
    SELECT *
    FROM Tache
    LEFT JOIN Historique ON reftTache=idTache
    WHERE date = 'yyyyy'
    union
    SELECT *
    FROM Tache
    LEFT JOIN Historique ON reftTache=idTache
    WHERE date = 'xxxxxx' ,


    Mais en mettant "en relation" ces resultat, en le rejoignant par la tache

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mars 2006
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Mars 2006
    Messages : 400
    Points : 562
    Points
    562
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT *
    FROM Tache
    LEFT JOIN Historique ON reftTache=idTache
    WHERE date = 'yyyyy' 
    union
    SELECT *
    FROM Tache
    LEFT JOIN Historique ON reftTache=idTache
    WHERE date = 'xxxxxx'
    Tu peux obtenir les mêmes résultats avec cette requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT *
    FROM Tache
    LEFT JOIN Historique ON reftTache=idTache
    WHERE date = 'yyyyy' OR date = 'xxxxx'
    Tu veux obtenir
    tous les résultats où date='yyyyy'
    et
    tous les résultats où date='xxxxx'
    Pour chaque résultat retourné par la requête, date sera soit ''yyyyy', soit 'yyyyy'.
    Cela revient donc à chercher
    tous les résultats où
    date = 'yyyyy'
    ou
    date = 'xxxxx'

    Essaye d'exécuter les 2 requêtes.
    Tu devrais obtenir les mêmes résultats.

  5. #5
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    ok merci, mais par contre c'est pas le résultat attendu, je me suis mal exprimé.
    Je cherche a obtenir:
    Tache, valeur de l'histo a la date xxx, valeur de l'histo à la date 'yyy'
    et donc la condition de jointure est bien sur la tache

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mars 2006
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Mars 2006
    Messages : 400
    Points : 562
    Points
    562
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Historique( date, refTache, valeur)
    Tache(idTache, libelle )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT *
    FROM Tache
      LEFT JOIN Historique as h1 ON h1.reftTache=idTache
        AND h1.date='yyyyy'
      LEFT JOIN Historique as h2 ON h2.reftTache=idTache
        AND h2.date='xxxxx'
    Pour lier 1 Historique à Tache, il faut 1 jointure.
    Pour lier 2 Historique à Tache, il faut 2 jointures.
    Ces 2 jointures sont identitiques puisque l'on connait les 2 dates.

  7. #7
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    merci on s'y approche!

    mais je ne veux que les taches qui sont dans Historique 2 et pour tous les histo2 je veux histo1 s'il existe ou NULL dans le cas contraire
    Et la seule condition de jointure que je vois entre les histo, c'est la tache!

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mars 2006
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Mars 2006
    Messages : 400
    Points : 562
    Points
    562
    Par défaut
    Pour n'avoir que les tâches présentes dans histo2, il faut rajouter une jointure pour ne pas prendre celles qui ne sont pas présentes dans histo2.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT DISTINCT idTache, libelle, h1.*, h2.*
    FROM Tache
      LEFT JOIN Historique AS h1 ON h1.reftTache=idTache
        AND h1.date='yyyyy'
      LEFT JOIN Historique AS h2 ON h2.reftTache=idTache
        AND h2.date='xxxxx'
      INNER JOIN Historique AS h ON h.reftTache=idTache
    Avec un INNER JOIN, les tâches non présentes dans Historique ne sont pas prises en compte.
    Pour n'obtenir qu'une seule fois chaque Tache, on utilise DISTINCT.

  9. #9
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    j'ai du mal a comprendre:
    la jointure porte t'elle sur l'ensemble des jointures qui la precede ou uniquement sur la jointure precedante?

    en tout cas c'est exactement ce que je veux mais je veux que ca ne porte que sur les taches de H2 (date='xxx') et non sur toutes les taches référencée par la table historique

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mars 2006
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Mars 2006
    Messages : 400
    Points : 562
    Points
    562
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT DISTINCT idTache, libelle, h1.*, h2.*
    FROM Tache
      LEFT JOIN Historique AS h1 ON h1.reftTache=idTache
        AND h1.date='yyyyy'
      LEFT JOIN Historique AS h2 ON h2.reftTache=idTache
        AND h2.date='xxxxx'
      INNER JOIN Historique AS h ON h.reftTache=idTache
    1. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      LEFT JOIN 'table' ON condition
      Cette jointure porte sur la table 'table' et sur les tables présentes dans la condition.
    2. Code : Sélectionner tout - Visualiser dans une fenêtre à part
        INNER JOIN Historique AS h ON h.reftTache=idTache
      Cette jointure porte sur h (Historique) et sur Tache.
      Elle permet d'obtenir toutes les tâches présentes dans Historique.
    3. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
        LEFT JOIN Historique AS h1 ON h1.reftTache=idTache
          AND h1.date='yyyyy'
      Cette requête porte sur h1 (Historique) et sur Tache.
      Elle associe à chaque tâche un historique, s'il exsite, pour lequel date='yyyyy'.
    4. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
        LEFT JOIN Historique AS h2 ON h2.reftTache=idTache
          AND h2.date='xxxxx'
      Cette requête porte sur h2 (Historique) et sur Tache.
      Elle associe à chaque tâche un historique, s'il exsite, pour lequel date='xxxxx'.

  11. #11
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    je suis désolé mais je n'y arrive pas...

    Le + simple est peut etre d'expliquer le résultat attendue:
    je voudrais
    Tache <----> H2 <----> H1
    avec uniquement les taches présentent dans H2

    si j'ai la table TAche
    T.id = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    H(id, refTache, valeur, date) 
    1      1      0.0     yyy
    2      2      0.0     yyy
    3      1      1.0     xxx
    4      2      0.0     xxx
    5      3      2.0     xxx
    6      8      5.0     eee
    7      8      3.5     fff
    ...


    Ex:avec h2.date='xxx' et h1.date='yyy'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    T.id   H2.id   H2.valeur   H1.id  H1.valeur
    1       3           1.0           1          0.0
    2       4           0.0           2          0.0
    3       5           2.0          NULL      NULL


    Donc dans mon idée, je pensais partir de H2 left join H1 sur la tache (c'est la seule chose qu'il aient en commun) et ensuite join tache sur H2
    Moi j'ai reussi a obtenir ce résultat en faisant des inner join sur les 3 tables, UNION les taches qui sont présentes dans H2 et pas dans H1 (en remplacant H1.valeur par 0). Je pense qu'il ya plus simple...!

    En tout cas, merci de votre patience

  12. #12
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mars 2006
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Mars 2006
    Messages : 400
    Points : 562
    Points
    562
    Par défaut
    Dans ce cas, procédons par étapes :
    1. sélectionner les Tache présentes dans Historique
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      SELECT DISTINCT idTache, libelle
      FROM Tache
        INNER JOIN Historique AS h ON h.reftTache=idTache
      Cette requête sélectionne toutes les tâches présentes dans Historique.

    2. sélectionner les Tache présentes dans Historique où date='xxx'
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      SELECT DISTINCT idTache, libelle
      FROM Tache
        INNER JOIN Historique AS h ON h.reftTache=idTache
          AND h.date='xxx'
      Cette requête sélectionne toutes les tâches présentes dans Historique et où date est 'xxx'.

    3. la suite, on la verra ensuite...
      Comprends-tu les requêtes précédentes ?

  13. #13
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    ok la je suis!

  14. #14
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mars 2006
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Mars 2006
    Messages : 400
    Points : 562
    Points
    562
    Par défaut
    1. sélectionner les Tache présentes dans Historique où date='xxx'
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      SELECT idTache, libelle, h2.valeur
      FROM Tache
        INNER JOIN Historique AS h2 ON h2.reftTache=idTache
          AND h2.date='xxxxx'
      histo2 est associé à la tâche.

    2. associer à Tache les Historique où date='yyy'
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      SELECT idTache, libelle, h2.valeur, h1.valeur
      FROM Tache
        INNER JOIN Historique AS h2 ON h2.reftTache=idTache
          AND h2.date='xxxxx'
        LEFT JOIN Historique AS h1 ON h1.reftTache=idTache
          AND h1.date='yyyyy'
      Il se peut que cette requête ne donne pas les résultats que tu attends.
      Mais l'important, lorsque tu as une requête complexe à créer, c'est de la faire par étapes, en la découpant en des requêtes simples.
      Ensuite, il suffit de regrouper ces requêtes en une seule pour obtenir les résultats attendus.

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

Discussions similaires

  1. Auto-jointure externe sur SQL server
    Par djam21 dans le forum Designer
    Réponses: 6
    Dernier message: 01/12/2011, 17h42
  2. Jointures externes sur une table de jointure
    Par mart1 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 10/10/2006, 01h33
  3. [DB2] Problèmes avec une Jointure externe sur des vues
    Par treivse dans le forum Langage SQL
    Réponses: 6
    Dernier message: 11/07/2006, 11h42
  4. Jointure Externe sur base ACCESS par Query Excel
    Par marie10 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 07/03/2006, 11h20
  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