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 :

Group By et Left Join lorsque ce dernier retourne aucun champ.


Sujet :

Requêtes MySQL

  1. #1
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut Group By et Left Join lorsque ce dernier retourne aucun champ.
    Deux tables:
    product, représentant des cartouches d'encres et qui -pour l'exemple- possède 2 champs: id et name
    cartridgeCompatibility, représentant les modèles d'imprimantes compatibles avec la cartouche et qui possède aussi 2 champs: modelId et cartridgeId

    Note: cartridgeCompatibility est une table de liaison qui gère les cartouches (par id) compatibles avec les modèles (par id) d'imprimantes.

    Ma requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT p.`id`, p.`name`, COUNT(c.modelId) as qte_modele
    	FROM `product` as p
    	LEFT JOIN `cartridgeCompatibility` as c ON (c.cartridgeId = p.id)
    	GROUP BY c.cartridgeId
    	ORDER BY p.`name` ASC;
    Le but:
    Faire afficher un tableau qui liste tous les produits, et qui pour chaque ligne, calcule combien de cartouches sont compatibles avec le produit.

    Le problème
    Simple ... et bien actuellement, avec cette requête, si un produit (cartouche) n'à pas de modèle d'imprimante associé, le produit ne sera tout simplement pas listé.

    Et comme la commande "Associer une imprimante" est une action qui est associé au listing du produit, impossible de créer mes association sans changer le fonctionnement de mon paneau d'administration



    Merci à l'avance de votre coup de pouce, j'espère avoir été clair et bref

  2. #2
    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 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Fait le GROUP BY sur le p.id :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT p.`id`, p.`name`, COUNT(c.modelId) AS qte_modele
    FROM `product` AS p
    LEFT JOIN `cartridgeCompatibility` AS c ON (c.cartridgeId = p.id)
    GROUP BY p.`id`
    ORDER BY p.`name` ASC;
    Il y a quelque chose de bizarre dans ton énoncé. Si j'ai bien lu et compris, un 'product' est une cartouche d'encre ?
    product, représentant des cartouches d'encres
    Pourquoi dis-tu alors :
    si un produit n'a pas de cartouche d'associée
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    Mon dieu, en effet, désolé de mon erreur (c'est ce que ca fait de rédiger à 2h du matin)

    Au lieu de:
    si un produit n'a pas de cartouche d'associée

    On devrait lire:
    si un produit n'a pas de modèle d'imprimante

    J'édite l'énoncé.


    Quelle est la différence entre le faire sur le p.id ou sur le c.cartridgeId ?

  4. #4
    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 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par FMaz Voir le message
    Quelle est la différence entre le faire sur le p.id ou sur le c.cartridgeId ?
    Le p.id est dans ton SELECT et pas l'autre. On ne sait jamais, c'est à essayer car normalement tous les p.id devraient être retrournés par la requête vu qu'on est en LEFT JOIN
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    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 016
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 016
    Points : 23 705
    Points
    23 705
    Par défaut
    Bonjour,

    Si MySQL laisse passer le fait que les champs qui ne sont pas dans la fonction d'agrégation ne doivent pas tous être dans le GROUP BY, c'est quand même une mauvaise habitude...
    Il vaut mieux (et d'autres SGBD n'autoriseraient pas cette syntaxe), mettre tous les champs qui ne sont pas dans la fonction d'agrégation dans le GROUP BY. Le champ c.cartridgeId dans le GROUP BY aurait renvoyé une erreur dans les autres SGBD...
    Dans le cas présent, en mettant product.id, ça n'est pas trop grave, mais c'est une bonne habitude à prendre .

    De même, en écrivant une jointure à gauche, il vaut mieux laisser, dans la condition de jointure, le champ de la table de gauche à gauche de l'égalité (ou de l'inégalité) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT p.`id`, p.`name`, COUNT(c.modelId) AS qte_modele
    FROM `product` AS p
    LEFT JOIN `cartridgeCompatibility` AS c ON (p.id = c.cartridgeId)
    GROUP BY p.`id`, p.`name`
    ORDER BY p.`name` ASC;
    ced
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  6. #6
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    Effectivement, si je fait le groupby sur le champs dans le select, ca marche #1... étrange.

    Dans tous les cas, merci !

  7. #7
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    ced: merci de ton explication, mais, je ne la comprend pas vraiment:
    Si MySQL laisse passer le fait que les champs qui ne sont pas dans la fonction d'agrégation ne doivent pas tous être dans le GROUP BY, c'est quand même une mauvaise habitude...
    Qu'est-ce que tu apelle "la fonction d'agrégation" ?
    Je vois que tu as rajouté p.`name` dans le GROUP BY, mais je ne comprend pas bien pourquoi.


    Aussi, est-ce que tu aurais de la documentation sur les LEFT, RIGHT et INNER JOIN qui soit clair et simple ? Car j'ai lu plusieurs bouquins, mais je n'arrive toujours pas à trouver comment optimiser l'utilisation de ces 3 fonctions. (Quand les utiliser, quand ne pas les utiliser).

    (... Je suis du genre à comprendre avec des contres exemples et c'est pas fréquent dans les bouquins ! )


    Dans tout les cas, merci encore, mon problème est résolu! (Mais j'aimerais bien comprendre pourquoi)

  8. #8
    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 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Quelques mots sur les jointures...

    INNER JOIN : Jointure interne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT a.id, a.nom, b.correspondance
    FROM a
    INNER JOIN b ON a.id = b.ida
    On ne prend que les lignes en correspondance dans les deux tables.
    S'il y a des lignes de a qui n'ont pas leur id en clé étrangère dans b, elles ne seront pas retournées. Idem pour les éventuelles lignes de b dont les ida en seraient pas (ou plus) dans a : elles ne seront pas retournées.

    Pour avoir toutes les lignes d'une table en indiquant la correspondance dans l'autre, on utilise la jointure externe LEFT OUTER JOIN ou RIGHT OUTER JOIN ou FULL OUTER JOIN (le mot OUTER est facultatif).
    Je prends toutes les lignes de a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT a.id, a.nom, b.correspondance
    FROM a 
    LEFT JOIN b ON a.id = b.ida
    Pour les lignes de a qui n'ont pas de correspondance, la colonne b.correspondance affichera NULL.

    On peut faire l'inverse en remplaçant LEFT par RIGHT et obtenir toutes les lignes de b avec NULL dans les colonnes a.id et a.nom s'il n'y a pas de correspondance.

    Avec un FULL JOIN, on obtient les deux, c'est à dire à la fois :
    - toutes les lignes de a avec NULL s'il n'y a pas de correspondance ;
    - toutes les lignes de b avec NULL s'il n'y a pas de a.id correspondant.

    Pour en savoir plus, voir le tutoriel de SQLPro.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  9. #9
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    Hum, ok, pour la différence entre inner ou outer, je pense saisir.
    Inner = si la jointure est impossible, la ligne retournée est skippé (pas de résultats partiel ou NULL )
    Outer = l'inverse


    Mais dans quel cas de figure est-ce qu'il faudrais utiliser un RIGHT JOIN et que le LEFT JOIN est impossible ?

    Et LEFT JOIN, ca se trouve à être un LEFT OUTER JOIN en réalité ?

    J'ai l'impression que je suis complètement dans le champs...

  10. #10
    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 016
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 016
    Points : 23 705
    Points
    23 705
    Par défaut
    Citation Envoyé par FMaz Voir le message
    Qu'est-ce que tu apelle "la fonction d'agrégation" ?
    Les fonctions COUNT, SUM, MIN, MAX... sont les fonctions d'agrégation (elles agrègent plusieurs lignes)
    Citation Envoyé par FMaz Voir le message
    Je vois que tu as rajouté p.`name` dans le GROUP BY, mais je ne comprend pas bien pourquoi.
    Parce que c'est obligatoire, puisque tout champ qui est en-dehors de ces fonctions d'agrégation participe à la définition de chacun des "groupes". MySQL est un peu permissif sur les champs à faire figurer dans le GROUP BY.

    Citation Envoyé par FMaz Voir le message
    Aussi, est-ce que tu aurais de la documentation sur les LEFT, RIGHT et INNER JOIN qui soit clair et simple ? Car j'ai lu plusieurs bouquins, mais je n'arrive toujours pas à trouver comment optimiser l'utilisation de ces 3 fonctions. (Quand les utiliser, quand ne pas les utiliser).
    Avec ce tutoriel, peut-être

    ced
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  11. #11
    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 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par FMaz Voir le message
    Mais dans quel cas de figure est-ce qu'il faudrais utiliser un RIGHT JOIN
    Le plus souvent, on utilise le LEFT JOIN parce que ça correspond à notre manière occidentale de lire les choses, de gauche à droite :
    Nom | Projet
    Dupont | Compta
    Durand | Paie
    Duchmol | NULL

    Ci-dessus, on liste les membres du personnel et on voit facilement ceux qui ne sont pas affectés à un projet. Mais rien n'empèche de faire l'inverse avec un RIGHT JOIN.

    Là où c'est parfois plus pratique d'utiliser le RIGHT JOIN, c'est quand une table est liée à plusieurs autres et que parmi les jointures on en met une en externe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT ...
    FROM a
    INNER JOIN b ON ...
    INNER JOIN c ON ...
    RIGHT JOIN d ON ...
    Ici par exemple, 'a' serait la table des projets, 'b' et 'c' seraient des tables contenant des informations relatives aux projets et 'd' serait la table du personnel. On afficherait ainsi pour chaque personne les infos relatives aux projets ou NULL quand il n'y a pas de projet.

    et que le LEFT JOIN est impossible ?
    Les cas d'impossibilité, que ce soit avec RIGHT ou LEFT JOIN, sont des cas de jointures complexes et surtout ambiguës que le SGBDR n'arrive pas à interpréter. Un peu comme une boucle infernale entre deux cellules d'une feuille Excel qui se font mutuellement référence.

    Et LEFT JOIN, ca se trouve à être un LEFT OUTER JOIN en réalité ?
    Oui c'est pareil. OUTER est facultatif.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  12. #12
    Membre confirmé
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Points : 640
    Points
    640
    Par défaut
    Génial, un gros merci !

    Il me reste le tuto à lire

  13. #13
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par ced Voir le message

    Parce que c'est obligatoire, puisque tout champ qui est en-dehors de ces fonctions d'agrégation participe à la définition de chacun des "groupes". MySQL est un peu permissif sur les champs à faire figurer dans le GROUP BY.

    ced
    Hello
    Attention, ceci peut encourager à effectuer vos "SELECT ... LEFT JOIN ... GROUP BY" à la truelle...

    Consultez http://cedric-duprez.developpez.com/...fier-group-by/ pour plus d'infos

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

Discussions similaires

  1. Problème de GROUP BY avec LEFT JOIN
    Par wenijah dans le forum Requêtes
    Réponses: 0
    Dernier message: 17/04/2012, 14h09
  2. Left Join et Group By récupérer dernières valeurs
    Par djboy dans le forum Requêtes
    Réponses: 2
    Dernier message: 17/06/2009, 09h32
  3. left join et group by
    Par eclesia dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 08/08/2007, 09h19
  4. requete avec left join et group by
    Par slc dans le forum Requêtes
    Réponses: 2
    Dernier message: 14/09/2004, 18h03
  5. Export d'une vue avec LEFT JOIN
    Par schnourf dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 22/05/2003, 13h57

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