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 :

Produit cartésien et jointure externe de plusieurs tables


Sujet :

Langage SQL

  1. #1
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 276
    Points : 13 553
    Points
    13 553
    Par défaut Produit cartésien et jointure externe de plusieurs tables
    Bonjour

    Le système est Mysql.

    • Le contenu de la table 'a' doit être présente intégralement
    • Le contenu de la table 'd' doit être présente intégralement
    • La table 'b' contient des informations à afficher, si possible. NULL sinon.
    • Les tables sont reliés comme suit: a <-> b <-> c <-> d


    J'ai tenté un produit cartésien des tables 'a' et 'd 'pour ensuite faire une jointure externe avec 'b' et 'c'.
    Le résultat ne me convient pas car il invente des données là où il devrait mettre NULL.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT DISTINCT d.d_nom, a.a_nom, b.b_info, b.b_info2
    FROM a
    CROSS d
    LEFT JOIN b ON b.a_nom=a.a_nom
    LEFT JOIN c ON c.c_nom=b.c_nom AND c.d_nom=d.d_nom
    ;
    Un enregistrement de 'a' croisé avec un enregistrement de 'd' donne des résultats pour 'b.info', ce qui est impossible.

    Quelle est la bonne requête pour obtenir mon résultat ?

  2. #2
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 385
    Points : 39 883
    Points
    39 883
    Billets dans le blog
    9
    Par défaut
    vous ne pouvez pas faire la jointure A<=>D puisqu'il faut passer par B puis C

    voici la requête standard
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT DISTINCT d.d_nom, a.a_nom, b.b_info, b.b_info2
    FROM a
    LEFT OUTER JOIN B
      ON b.a_nom=a.a_nom
    LEFT OUTER JOIN C
      ON c.c_nom=b.c_nom 
     AND c.d_nom=d.d_nom
    FULL OUTER JOIN D
      ON D.xxxx = C.xxxx
     AND D.yyyy = C.yyyy	
    ;
    Comme MySQL ne connait pas le full join vous devrez faire
    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
    SELECT DISTINCT d.d_nom, a.a_nom, b.b_info, b.b_info2
    FROM a
    LEFT OUTER JOIN B
      ON b.a_nom=a.a_nom
    LEFT OUTER JOIN C
      ON c.c_nom=b.c_nom 
     AND c.d_nom=d.d_nom
    LEFT OUTER JOIN D
      ON D.xxxx = C.xxxx
     AND D.yyyy = C.yyyy	
     
    UNION
     
    SELECT DISTINCT d.d_nom, a.a_nom, b.b_info, b.b_info2
    FROM a
    LEFT OUTER JOIN B
      ON b.a_nom=a.a_nom
    LEFT OUTER JOIN C
      ON c.c_nom=b.c_nom 
     AND c.d_nom=d.d_nom
    RIGHT OUTER JOIN D
      ON D.xxxx = C.xxxx
     AND D.yyyy = C.yyyy	
    ;
    Edit : j'ajoute qu'en terme de performances, MySQL sera beaucoup plus lent que tout autre SGBD, puisque sa "lacune" sur le full outer join lui impose un dé doublonnage des résultats de l'union (pas de union all donc)

  3. #3
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 276
    Points : 13 553
    Points
    13 553
    Par défaut
    Merci pour cette réponse.

    Malheureusement, il ne fait pas le produit cartésien de a et d.

    J'imagine que, dans cette syntaxe, chaque jointure prend le résultat de la jointure précédente.
    Mais comment expliquer, lors de la dernière jointure, que 1 colonne de a doit se multiplier avec une colonne de d ?

    Parce que là, il prend un enregistrement de d, ne trouve pas de correspondance dans c et s'arrête; c'est-à-dire qu'il affiche:
    Alors que je voudrais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    truc1;machin;NULL;NULL
    truc2;machin;NULL;NULL
    truc3;machin;NULL;NULL
    truc4;machin;NULL;NULL
    [edit]Pardon, j'ai interverti les colonnes. La deuxième colonne est d et la première est a[/edit]

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 385
    Points : 39 883
    Points
    39 883
    Billets dans le blog
    9
    Par défaut
    Ok tout A et D quoi qu'il arrive, mais du coup votre requete sembe OK, pouvez vous communiquer le jeu d'essai et le résultat qui vous fait dire "Le résultat ne me convient pas car il invente des données là où il devrait mettre NULL"

  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 920
    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 920
    Points : 51 712
    Points
    51 712
    Billets dans le blog
    6
    Par défaut
    Le produit cartésien se fait avec CROSS JOIN. A me lire : http://sqlpro.developpez.com/cours/s...ntures/#LIII-E

    A +

  6. #6
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 276
    Points : 13 553
    Points
    13 553
    Par défaut
    table a:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    truc1
    truc2
    truc3
    truc4
    table b:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    truc1;2015;toto
    truc1;2015;tata
    table c:
    table d:
    Résultat requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    gogo;truc1;2015
    gaga;truc1;2015
    gigi;truc1;2015
    gogo;truc2;NULL
    gaga;truc2;NULL
    gigi;truc2;NULL
    gogo;truc3;NULL
    gaga;truc3;NULL
    gigi;truc3;NULL
    gogo;truc4;NULL
    gaga;truc4;NULL
    gigi;truc4;NULL
    En rouge, la ligne incorrecte.
    Les deux premiers champs me conviennent parfaitement. Mais les champs suivants ne correspondent pas dans la ligne rouge.

  7. #7
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 276
    Points : 13 553
    Points
    13 553
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Le produit cartésien se fait avec CROSS JOIN. A me lire : http://sqlpro.developpez.com/cours/s...ntures/#LIII-E

    A +
    Fort bien. C'est pour cela que la requête initiale commence par un CROSS JOIN. Mais cela n'explique pas pourquoi j'ai une faute dans le résultat.

    [edit] Je me rends compte qu'en anonymisant le nom des tables, le "JOIN" de "CROSS JOIN" a disparu. Mais "CROSS JOIN" est bien présent dans la requête. [/edit]

  8. #8
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 385
    Points : 39 883
    Points
    39 883
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Fort bien. C'est pour cela que la requête initiale commence par un CROSS JOIN.
    Tout à fait

    Citation Envoyé par Flodelarab Voir le message
    Mais cela n'explique pas pourquoi j'ai une faute dans le résultat.
    Il n'y en a pas :

    A cross join D donne
    Truc1 GOGO
    Truc1 GAGA
    Truc1 GIGI
    Truc2 GOGO
    Truc2 GAGA
    Truc2 GIGI
    Truc3 GOGO
    Truc3 GAGA
    Truc3 GIGI
    Truc4 GOGO
    Truc4 GAGA
    Truc4 GIGI

    Et A left outer join B construit
    truc1 truc1 2015 TOTO
    truc1 truc1 2015 TATA

    truc2 null null null
    truc3 null null null
    truc4 null null null

    Il est donc normal d'obtenir GIGI truc1 2015 (une seule fois a cause du distinct)

  9. #9
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 276
    Points : 13 553
    Points
    13 553
    Par défaut
    Ce que je comprends de ta réponse est que la table d passe par la table a pour prendre les données de la table b .

    Ne cherchons plus, j'ai trouvé. J'utilise bêtement une sous-requête:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT DISTINCT ss.d_nom, ss.a_nom, b.info
    FROM 
    b
    JOIN c ON c.c_nom=b.c_nom
    RIGHT JOIN ( SELECT a.a_nom as "a_nom", d.d_nom as "d_nom"
                FROM a,d 
                ) ss ON b.a_nom=ss.a_nom AND c.d_nom=ss.d_nom
    ;
    Et j'obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    gogo;truc1;2015
    gaga;truc1;2015
    gigi;truc1;NULL
    gogo;truc2;NULL
    gaga;truc2;NULL
    gigi;truc2;NULL
    gogo;truc3;NULL
    gaga;truc3;NULL
    gigi;truc3;NULL
    gogo;truc4;NULL
    gaga;truc4;NULL
    gigi;truc4;NULL

  10. #10
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 385
    Points : 39 883
    Points
    39 883
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Ce que je comprends de ta réponse est que la table d passe par la table a pour prendre les données de la table b
    Absolument pas !
    Mais il faut bien mettre sur une ligne le résultat du cross join A-D et celui du left join A-B, le résultat est donc cohérent avec ces 2 jointures
    L'essentiel ait que vous ayez trouvé une requete correspondant à votre besoin

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

Discussions similaires

  1. Jointure externe sur plusieurs tables
    Par Xeuch dans le forum Requêtes
    Réponses: 1
    Dernier message: 19/08/2013, 21h12
  2. Jointure externe sur plusieurs tables
    Par huître dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 18/09/2011, 22h57
  3. Requete SQL jointure externe sur plusieurs tables
    Par mattmax dans le forum Développement
    Réponses: 4
    Dernier message: 28/12/2010, 11h07
  4. jointures externes entre plusieurs tables
    Par hacksi dans le forum Access
    Réponses: 22
    Dernier message: 15/05/2006, 17h26
  5. Jointure externe sur 2 tables
    Par Danae dans le forum Langage SQL
    Réponses: 11
    Dernier message: 19/07/2005, 16h37

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