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

Requêtes MySQL Discussion :

Jointure sur 3 tables


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 4
    Par défaut Jointure sur 3 tables
    Bonjour :]

    Je ne parviens pas à obtenir le résultat voulu sur une requête. Tout du moins je ne sais pas comment m'y prendre.

    Pour faire simple, j'ai 3 tables:

    ARTICLES
    id_art
    texte

    CATEGORIES
    id_cat
    titre

    ART2CAT
    id_art
    id_cat


    La table ART2CAT fait le lien entre les 2 autres tables. Un article pouvant avoir plusieurs catégories et une catégories plusieurs articles, la cardinalité est donc 1,n -- 0,n

    Pour récupérer un seul article, son texte et le titre des catégories qui lui sont associées, je fais cette requête:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT a.*, c.* FROM articles a 
    INNER JOIN art2cat a2c ON a2c.id_article = a.id_article
    INNER JOIN categories c ON c.id_categorie = a2c.id_categorie
    WHERE a.id_article = 1 LIMIT 1
    En supposant que l'article avec l'ID 1 a 2 catégories, cette requête renvoit 2 lignes que je peux traiter en php pour n'afficher qu'une seule fois l'article. (Cette méthode me semble déjà assez suspecte en fait^^')

    Là où j'ai vraiment un problème, c'est lorsqu'il s'agit d'afficher plusieurs articles. Imaginons que je souhaite afficher 5 articles:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT a.*, c.* FROM articles a 
    INNER JOIN art2cat a2c ON a2c.id_article = a.id_article
    INNER JOIN categories c ON c.id_categorie = a2c.id_categorie
    ORDER BY id_art DESC LIMIT 5
    Dans ce cas, l'article avec l'ID 1 qui a 2 catégories renvoie déjà 2 lignes. Quelque soit le nombre de catégories associés aux autres articles, je ne pourrai de toute façon afficher que 4 articles différents et non 5, comme initialement prévu.

    Quelle est la manière la plus optimisée d'obtenir les résultats attendus?

    J'ai bien pensé à exécuter une sous-requête qui va chercher à chaque article les catégories qui lui sont associées. Mais si je veux afficher 20 articles, je vais me retrouver avec 21 requêtes. Bonjour l'optimisation

    Cette cardinalité est pourtant courante... J'ai vraiment l'impression de passer à côté d'une évidence >_<

    Merci d'avance pour l'aide que vous pourrez m'apporter^^

  2. #2
    Membre éprouvé
    Inscrit en
    Septembre 2007
    Messages
    169
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 169
    Par défaut
    Le group by sert à ca

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT a.*, c.* FROM articles a 
    INNER JOIN art2cat a2c ON a2c.id_article = a.id_article
    INNER JOIN categories c ON c.id_categorie = a2c.id_categorie
    GROUP BY a.id_article
    ORDER BY id_art DESC LIMIT 5

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 4
    Par défaut
    Le group by sert à ca
    Merci pour ta réponse

    J'ai effectivement omis le GROUP BY dans la requête. Ceci dit, j'avais déjà testé cette requête avec le GROUP BY également et je n'ai toujours pas le résultat attendu puisque l'article avec l'ID 1 va s'afficher avec une seule catégorie alors qu'il y en a 2 qui lui sont associées.

    Pour résumer:

    - avec le GROUP BY, 5 articles différents résultent de la requête mais la gestion des catégories n'est pas complète.
    - sans le GROUP BY, la gestion des catégorie est complète mais la requête ne renvoie pas les 5 articles voulus.

  4. #4
    Membre chevronné Avatar de binouzzz19
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    385
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2007
    Messages : 385
    Par défaut
    et ca ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT a.*, c.* FROM articles a 
    INNER JOIN art2cat a2c ON a2c.id_article = a.id_article
    INNER JOIN categories c ON c.id_categorie = a2c.id_categorie
    GROUP BY a.id_article, c.id_categorie
    ORDER BY id_art DESC LIMIT 5
    Je ne fais plus trop d'sql en ce moment, dsl si je dis de la mer**

  5. #5
    Membre éprouvé
    Inscrit en
    Septembre 2007
    Messages
    169
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 169
    Par défaut
    Non, ca reviendrait au même que sans group by.

    Sinon y'a aussi le GROUP_CONCAT :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT a.*, c.*, GROUP_CONCAT(c.id_categorie) FROM articles a 
    INNER JOIN art2cat a2c ON a2c.id_article = a.id_article
    INNER JOIN categories c ON c.id_categorie = a2c.id_categorie
    GROUP BY a.id_article
    ORDER BY id_art DESC LIMIT 5

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 4
    Par défaut
    Non, je suis désolé binouzzz19, ça ne marche pas mieux. D'ailleurs, ça n'a aucun effet sur les résultats.

    C'est peut être moi qui exprime mal mon problème

    En fait, ce que je recherche, c'est un résultat proche de ce que font les plateformes de blogs comme Wordpress, LifeType... Leurs sources sont relativement opaques et je ne parviens pas à comprendre comment ils effectuent cette requête. Pourtant, leur base de données sont modélisées de la même manière que ce que j'ai exposé.

    Un article peut avoir plusieurs catégories et comme il n'y a pas de lien direct entre la table ARTICLES et la table CATEGORIES, il faut passer par la table ART2CAT.

    Voilà grosso-modo ce qui donnerait un résultat cohérent:

    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
     
    #Requête pour obtenir les articles
    $query = 'SELECT * FROM articles ORDER BY id_article DESC LIMIT 5';
    $result=mysql_query($query);
     
    while ($array=mysql_fetch_array($result)) {
    extract($array);
     
    #Requête pour obtenir les catégories associées à chaque article issu de la 1ere requête
       $query = 'SELECT c.id_cat, c.titre_cat 
    FROM categories c 
    INNER JOIN art2cat a2c ON a2c.id_cat = c.id_cat 
    WHERE a2c.id_article = '.$id_article;
       $result=mysql_query($query);
       while ($array=mysql_fetch_array($result)) {
       extract($array);
        #Ici on concatène les titres de catégories correspondant à un article -> variable $toutes_les_cats_dun_article
        }
    #Ici on concatène les données de chaque article + $toutes_les_cats_dun_article
    }
    Mais bon... Une requête dans une boucle >__< Ici, ça boucle 5 fois donc on fait 6 requêtes. Mais si je décide de mettre la limite à 20, on atteind un joli score de 21 requêtes...
    Il y a forcément un moyen d'optimiser ce code, hein? Quand même?^^'

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 4
    Par défaut
    Excuse moi kangaxx, on a posté en même temps.

    GROUP_CONCAT!
    Une fonction magique. Mes cours sont trop loin, je l'avais oubliée!

    Ca marche. On a un résultat exploitable avec une seule requête.

    En revanche, si l'on applique la fonction uniquement sur des entiers, en l'occurence les id_cat, il faut écrire GROUP_CONCAT(CAST(c.id_cat as CHAR)) car GROUP_CONCAT renvoie une chaine en varchar. Sans ça, on n'obtient que des "blob".

    Dans mon cas, on pourrait même appliquer GROUP_CONCAT sur titre_cat. Du coup, il retourne sur une ligne correspondant à un article tous les titres de catégories qui lui sont associées: "titre_cat1,titre_cat2"

    Merci kangaxx :]

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

Discussions similaires

  1. jointure sur 3 tables
    Par jojo22222 dans le forum Requêtes
    Réponses: 5
    Dernier message: 23/01/2006, 22h47
  2. Jointure sur 3 tables
    Par tonymontana4192 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 21/11/2005, 13h24
  3. [MySQL] Jointure sur une table déjà jointe
    Par genova dans le forum Requêtes
    Réponses: 3
    Dernier message: 18/10/2005, 23h54
  4. jointure sur TROIS tables
    Par caribou_belle dans le forum Langage SQL
    Réponses: 8
    Dernier message: 01/03/2004, 11h20
  5. Jointure sur 2 tables de bases différentes
    Par Celina dans le forum Langage SQL
    Réponses: 10
    Dernier message: 10/11/2003, 11h56

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