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 :

Double jointure externe


Sujet :

Langage SQL

  1. #1
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Points : 2 273
    Points
    2 273
    Par défaut Double jointure externe
    Bonjour,
    j'ai un léger problème de jointure que je n'arrive pas à résoudre.
    ci-dessous les tables :

    biblio_texts
    id | title | #id_book (defaut = 0) | #id_review (defaut = 0)

    biblio_books
    id | title

    biblio_reviews
    id | title

    Un texte peut être lié à un ouvrage, une revue ou à rien.
    J'aimerais récupérer tous les textes, revues et ouvrages.
    Pour pouvoir récupérer les revues et les ouvrages non liés à des textes je suis parti sur une jointure externe. J'arrive actuellement à afficher soit les revues :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $sql = 'SELECT * FROM biblio_texts
    			RIGHT OUTER JOIN (biblio_reviews)
    				ON (biblio_reviews.id = biblio_texts.id_review)';
    soit les ouvrages :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $sql = 'SELECT * FROM biblio_texts
    			RIGHT OUTER JOIN (biblio_books)
    				ON (biblio_books.id = biblio_texts.id_book)';
    Mais je voudrais tout regrouper pour pouvoir afficher un tableau du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TitreTexte | TitreRevue | TitreOuvrage
    rien | UnTitredeRevue | rien
    rien | UnTitredeRevue2 | rien
    rien | rien | UnTitreOuvrage
    rien | rien | UnTitreOuvrage2
    UnTitre | UnTitredeRevue3 | rien
    UnTitre2 | rien | UnTitreOuvrage127
    UnTitre3 | UnTitredeRevue8 | rien
    UnTitre4 | rien | rien
    J'abouti donc à cette requête mais qui fait ramer le seveur à gogo et qui semble ne pas fonctionner (j'ai entre 500 et 1000 enregistrements par table) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $sql = 'SELECT * FROM biblio_texts
    			RIGHT OUTER JOIN (biblio_reviews, biblio_books)
    				ON (biblio_reviews.id = biblio_texts.id_review
    				AND biblio_books.id = biblio_texts.id_book)';
    Je précise que j'ai créé des index sur les clés externes (id_book et id_review) de la table biblio_texts.
    Voilà si quelqu'un a une solution ca m'aiderait bien.
    Merci d'avance

    (J'ai vu plusieurs posts intitulés "double jointure externe" mais je n'ai pas réussi à adapter les réponses à mon cas...)

  2. #2
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 034
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 034
    Points : 23 770
    Points
    23 770
    Par défaut
    Essaie ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT * 
    FROM biblio_texts
    RIGHT OUTER JOIN biblio_reviews	ON biblio_texts.id_review = biblio_reviews.id
    RIGHT OUTER JOIN biblio_books ON biblio_texts.id_book = biblio_books.id
    Prends l'habitude, dans l'écriture de la condition de jointure, de bien mettre à gauche la première table et à droite la seconde table.

    Je n'ai pas testé...

    ced

  3. #3
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Points : 2 273
    Points
    2 273
    Par défaut
    Merci pour le conseil judicieux.
    En ce qui concerne la requête je l'avais déjà tentée mais j'ai un :

    #1120 - Dépendance croisée dans une clause OUTER JOIN. Vérifiez la condition ON

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    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
    C'est dans ce sens qu'il faut faire les jointures si biblio_texts est la "table de départ"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    biblio_texts
    LEFT JOIN biblio_reviews ...
    LEFT JOIN biblio_books ...

  5. #5
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    Conceptuellement, un 'livre' et une 'revue' sont tous deux des 'ouvrages' de 'type' différent.

    On pourrait donc avoir :
    - une table Ouvrages(id_ouvrage, titre_ouvrage, type_ouvrage)
    - une table Textes(id_texte, titre_texte, #id_ouvrage)

    Et la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT Textes.titre_texte, Ouvrages.titre_ouvrage, Ouvrages.type_ouvrage
    FROM Textes, Titres
    WHERE Texte.id_ouvrage = Ouvrages.id_ouvrage

  6. #6
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Points : 2 273
    Points
    2 273
    Par défaut
    Citation Envoyé par vmolines Voir le message
    C'est dans ce sens qu'il faut faire les jointures si biblio_texts est la "table de départ"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    biblio_texts
    LEFT JOIN biblio_reviews ...
    LEFT JOIN biblio_books ...
    Le souci est qu'avec cette requête je n'aurai pas les ouvrages et les revues qui ne sont pas liés à un article.

    Au sujet de la conception, effectivement ca pourrait être une solution mais j'ai un paquet d'autres champs qui font que les 2 entités ont intérêt à être séparés.

  7. #7
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par Djakisback Voir le message
    j'ai un paquet d'autres champs qui font que les 2 entités ont intérêt à être séparés.
    Alors tu peux avoir une spécialisation de Livre et de Revue sous Ouvrages. Dans Ouvrages, tu mets tous les attributs communs aux livres et aux revues (ceux que j'ai cités et peut-être d'autres que je ne connais pas dans ton contexte) et dans les deux autres tables (Livres, Revues) seulement les attributs spéciaux à chacune de ces catégories. En UML on dit que Livres et Revues 'héritent' de Ouvrages.

  8. #8
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Points : 2 273
    Points
    2 273
    Par défaut
    Effectivement ca pourrait être plus propre et plus simple, je vais réfléchir à la question, merci.

    Si quelqu'un a une soluce pour palier au problème en l'état actuel ça m'intéresse également.

    Il doit surement y avoir moyen de regrouper ces 2 requêtes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $sql = 'SELECT * FROM biblio_texts
    			RIGHT OUTER JOIN (biblio_reviews)
    				ON (biblio_texts.id_review = biblio_reviews.id)';
     
    $sql = 'SELECT * FROM biblio_texts
    			RIGHT OUTER JOIN (biblio_books)
    				ON (biblio_texts.id_book = biblio_books.id)';

  9. #9
    Membre régulier
    Inscrit en
    Septembre 2007
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 63
    Points : 71
    Points
    71
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT DISTINCT TEXT.ID_TEXT
      FROM BIBLIO_TEXTS TEXT
     WHERE NOT EXISTS
     (SELECT 'X' FROM BIBLIO_BOOKS OUV WHERE OUV.ID_TEXT = TEXT.ID_TEXT)
       AND NOT EXISTS
     (SELECT 'X' FROM BIBLIO_REVIEWS REV WHERE REV.ID_TEXT = TEXT.ID_TEXT)
    UNION
    SELECT DISTINCT OUV.ID_OUV
      FROM BIBLIO_BOOKS OUV
    UNION
    SELECT DISTINCT REV.ID_REVIEW FROM BIBLIO_REVIEWS REV
    Bon la tu as tous les resultats sur la meme colonne
    Explication
    1er select :
    ramene tous les texts qui ne sont pas dans des review ou books
    2eme
    Ramene toutes les review
    3eme
    Ramene tous les books

    a toi de jouer avec ca !

  10. #10
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Points : 2 273
    Points
    2 273
    Par défaut
    Merci pour la réponse ^^.
    Argh je suis en MySql 4.0 qui ne gère pas les sous-requêtes :/ je n'ai donc pas pu tester les résultats mais je pense que la requête devrait planter car il faut le même nombre de colonnes pour les tables avec un UNION. De même que ceci ne peut pas fonctionner si les tables reviews et books n'ont pas le même nombre de champs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    (SELECT SQL_CALC_FOUND_ROWS * FROM biblio_texts
                RIGHT OUTER JOIN biblio_books
                    ON biblio_texts.id_book = biblio_books.id) 
                UNION
                    (SELECT * FROM biblio_texts
                RIGHT OUTER JOIN biblio_reviews
                    ON biblio_texts.id_review = biblio_reviews.id)
     
                    ORDER BY biblio_texts.title
                    ;
    Je crois que je vais songer sérieusement à revoir le Modèle Physique.

  11. #11
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Points : 2 273
    Points
    2 273
    Par défaut
    Bon j'ai modifié le modèle et je me retrouve avec juste la table books et la table texts. Je fais une jointure externe bidirectionnelle pour afficher les 'textes sans book', les 'textes avec book' et les 'books sans texte'.

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    (SELECT SQL_CALC_FOUND_ROWS * FROM biblio_texts
    			LEFT OUTER JOIN biblio_books
    				ON biblio_texts.id_book = biblio_books.id)
     
    		UNION
    				(SELECT * FROM biblio_texts
    			RIGHT OUTER JOIN biblio_books
    				ON biblio_texts.id_book = biblio_books.id)
     
    				ORDER BY biblio_texts.title ASC

    et ca fonctionne, je récupère bien toutes les combinaisons possibles :

    titreTexte | titreOuvrage
    rien | unTitre
    unTitre | unTitre
    unTitre | rien
    Le problème est que je dois utiliser REPLACE() dans le ORDER BY :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    (SELECT SQL_CALC_FOUND_ROWS * FROM biblio_texts
    			LEFT OUTER JOIN biblio_books
    				ON biblio_texts.id_book = biblio_books.id)
     
    		UNION
    				(SELECT * FROM biblio_texts
    			RIGHT OUTER JOIN biblio_books
    				ON biblio_texts.id_book = biblio_books.id)
     
    				ORDER BY REPLACE(biblio_texts.title, '\"', '') ASC

    Et là ca passe plus, j'ai un beau :
    Le champ 'id' ne peut être vide (null)
    Si je mets le ORDER BY dans les 2 SELECT ca fonctionne mais évidemment le tri se fait par SELECT et non sur le résultat de UNION.

    Si quelqu'un a une idée sur la question (sans sub-select)...

Discussions similaires

  1. Effectuer une "double" jointure externe
    Par sat83 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 12/07/2013, 13h31
  2. Double jointure externe sur une table
    Par astridette dans le forum SQL
    Réponses: 2
    Dernier message: 30/03/2012, 13h33
  3. Double jointure externe
    Par fozzeuh dans le forum SQL
    Réponses: 4
    Dernier message: 28/10/2010, 14h09
  4. requete avec double jointure externe
    Par cdu dans le forum Langage SQL
    Réponses: 8
    Dernier message: 04/01/2006, 14h54
  5. Doubles jointures externes....
    Par HPJ dans le forum Langage SQL
    Réponses: 2
    Dernier message: 16/11/2004, 15h28

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