Services : Actualité Emploi Blog Forum Flux
Formation Trafic : Référencement Liens sponsorisés Affiliation Ecommerce Nom de domaine E-réputation Marketing Mobile Black Hat
Formation Technique : Performance Web Html Css Sql Curl Asp Dotnet Php Ajax Wordpress Twitter Google Analytics

Forum Oseox
Oseox

tutoriel mysql et clause group by

Forum Référencement et Trafic
Nous sommes le Mer 22 Nov 2017 23:02

Heures au format UTC [ Heure d’été ]




Poster un nouveau sujet Répondre au sujet
Auteur Message
MessagePosté: Ven 23 Oct 2009 11:59 
Bonjour,

Je suis responsable de système documentaire et je me lance également bientôt dans une activité de développement web. J'ai deux trois bases en php/mysql, html/css et javascript (notamment jquery), mais il va falloir que je les améliore considérablement, d'où ma présence sur ce site.

Histoire de me remettre à niveau je viens de suivre en express le tuto mysql de Nicolas Galle. Il me semble que la partie concernant la clause group by présente un problème.

Pour rappelle on a une table etudiant avec les champs id_etudiant, nom, prenom, moyenne, domicile.

La requête utilisant la clause group by donnée en exemple est la suivante :
Code:
select domicile, prenom, max(moyenne) as moymax from etudiant group by domicile

Ce qui donne effectivement une liste référençant les localisation avec la moyenne la plus haute pour chacune d'entre-elle, mais le prénom ne correspond pas à cette moyenne. Par exemple si l'on se réfère à la page du tuto on voit que pour Grenoble la meilleure moyenne est 16 est que le prénom associé est Adrien. Ors, si on se réfère à la partie du tuto on insère les enregistrements dans la table, on peut constater que cet Adrien a en fait 11 de moyenne.

Il me semble donc que dans la requête formulée tel quel, le prénom affiché est le premier que l'on trouve dans la table et non celui associé à la meilleure moyenne. Deux questions suite à cette remarque :
- pourquoi ?
- comment associer le bon prénom à la moyenne ?

Merci de vos réponses,
Timothée


Haut
 Profil Envoyer un e-mail  
 
MessagePosté: Ven 23 Oct 2009 12:58 
Professionnel
Professionnel
Avatar de l’utilisateur
Qui dit GROUP BY implique obligatoirement d'avoir une expression d'agrégation comme sélection (en dehors de domincile puisqu'il est ciblé), ce qui n'est pas le cas dans cet exemple qui est par conséquent erroné (prenom = expression de non-agrégation), en clair, GROUP BY doit correspondre exactement à l'expression figurant dans la liste de sélection.

Là c'est surement le premier prénom dans la base qui matche qui est affiché, et c'est tout à fait normal.

Une approche :

Code:
SELECT prenom, domicile, moyenne AS moymax
FROM etudiant
WHERE moyenne
IN (

SELECT MAX( moyenne )
FROM etudiant
GROUP BY domicile
)


Haut
 Profil Envoyer un e-mail  
 
MessagePosté: Ven 23 Oct 2009 14:03 
Administrateur
Avatar de l’utilisateur
Bonjour,

Nicolas confirmera mais pour avoir lu l'ensemble des tutoriels, je crois qu'il ne faut pas vraiment tenir compte forcément des valeurs présentées d'un tutoriel à l'autre.


Haut
 Profil Envoyer un e-mail  
 
MessagePosté: Ven 23 Oct 2009 14:21 
Re bonjour,

Et merci pour vos réponses.

Effectivement c'est le premier prénom qui matche (et dans ce cas là c'est bien les mêmes valeurs entre les différents tuto, j'ai de mon côté fait les manip et on tombe bien sur le résultat affiché dans la page concernant group by du tuto en suivant l'ensemble du tuto).

Du coup j'ai testé la piste donnée par Stéphane, piste dont je comprends bien la logique et qui fonctionne déjà mieux.

Le comportement de la requête reste cependant étrange puisqu'elle m'affiche maintenant plusieurs résultat pour une localisation (Grenoble encore... non là je pense que c'est juste un hasard, d'ailleurs j'ai testé avec min(moyenne) et ça bug encore mais avec Lyon cette fois).

Pourtant quand j'exécute la sous-requête indépendamment :
Code:
select max(moyenne) from etudiant group by domicile

j'obtiens bien une seule moyenne (la plus haute) par localisation !

Merci tout de même pour ta réponse Stéphane qui donne une bonne clé (si j'ose dire ;) ) de compréhension.

Timothée


Haut
 Profil Envoyer un e-mail  
 
MessagePosté: Ven 23 Oct 2009 14:41 
Professionnel
Professionnel
Avatar de l’utilisateur
Citation:
Nicolas confirmera mais pour avoir lu l'ensemble des tutoriels, je crois qu'il ne faut pas vraiment tenir compte forcément des valeurs présentées d'un tutoriel à l'autre

Liés ou pas, je n'ai pas lu les tutoriels, mais placer 1 expression non-agrégée (en l'occurrence prenom) dans une requête avec GROUP BY est faux si cette expression n'est pas dans la clause en question ;)
Citation:
Le comportement de la requête reste cependant étrange puisqu'elle m'affiche maintenant plusieurs résultat pour une localisation

Oups effectivement, je la corrige :
Code:
SELECT prenom, domicile, moyenne AS moymax
FROM etudiant ee
WHERE moyenne
IN (

SELECT MAX( moyenne )
FROM etudiant e
WHERE ee.domicile=e.domicile
GROUP BY domicile
)


Plusieurs résulats sur une même ville peuvent toujours apparaître : si 2 étudiants ou plus de la même ville sont premiers ex-aecquo, si tu ne souhaites qu'un tuple, il te faudra modifier ceci et taper du côté de la fonction GROUP_CONCAT :

Code:
SELECT GROUP_CONCAT(prenom), domicile, moyenne AS moymax
FROM etudiant ee
WHERE moyenne
IN (

SELECT MAX( moyenne )
FROM etudiant e
WHERE ee.domicile=e.domicile
GROUP BY domicile
)
GROUP BY domicile


Haut
 Profil Envoyer un e-mail  
 
MessagePosté: Ven 23 Oct 2009 15:42 
Merci, tout marche nickel,

Bon, il me reste à comprendre pourquoi il y a besoin de rajouter des indices (on peut appeler ça comme cela, je parle de e et de ee ?) à la table pour n'avoir qu'un résultat par ville ...

En fait je comprends la logique, ce que je ne comprends pas du coup c'est qu'avec la requête suivante :
Code:
SELECT prenom, domicile, moyenne AS moymax
FROM etudiant
WHERE moyenne
IN (
SELECT MAX( moyenne )
FROM etudiant
GROUP BY domicile
)

on obtient plusieurs résultat pour certaines villes mais pas pour toutes (en l'occurrence cela me donne plusieurs résultats pour Grenoble mais pas pour Lyon ou Cereste - pour laquelle j'ai ajouté deux enregistrements pour voir), ce qui devrait être le cas non ?

Comme mon but ici est de comprendre le fonctionnement pour pouvoir l'appliquer ensuite et non le résultat pur de cette requête je me permets de continuer à te solliciter Stéphane :oops:

Merci encore

Timothée


Haut
 Profil Envoyer un e-mail  
 
MessagePosté: Ven 23 Oct 2009 16:03 
Professionnel
Professionnel
Avatar de l’utilisateur
Pourquoi ? 2 raisons : la première, je ne suis pas très attentionné :)
Pour la seconde, prenons un exemple simple :

--------
jacques montpellier 19
robert montpellier 7
joe paris 3
annie paris 18
alice beziers 3
hervé sete 1
jean sete 16
marie sete 16
--------

Code:
SELECT MAX (moyenne) FROM etudiant GROUP BY domicile

renvoie la liste des moyennes maximales pour chaque domicile, selon l'exemple (19,18,3,16)
et la requête qui l'appelle :
Code:
SELECT prenom, domicile, moyenne AS moymax FROM etudiant WHERE moyenne IN(...)

Va sélectionner tout le beau monde qui a les notes (19,18,3,16) ce qui va faire ressortir Joe de Paris (qui est un cancre) parce que Alice de Béziers est première dans sa ville avec la brillante note de 3, or, Joe n'est pas premier à Paris (puisque c'est Annie).

Il faut donc sélectionner également selon les domiciles, et comme il s'agit de la même table, on est obligé de créer un "alias" sur les tables, d'où le "etudiant e". "e" devient un alias d'etudiant, et "ee" un autre alias pour la même table.

Le 'ee.domicile=e.domicile' stipule qu'en plus de sélectionner les notes maximales (19,18,3,16), le domicile doit correspondre avec celui de la première requête.


Haut
 Profil Envoyer un e-mail  
 
MessagePosté: Ven 23 Oct 2009 16:08 
Effectivement c'est très clair, je pense que là maintenant j'ai bien compris le principe

Merci beaucoup pour ton aide et tes explications :D

Timothée


Haut
 Profil Envoyer un e-mail  
 
MessagePosté: Ven 23 Oct 2009 16:26 
Administrateur
Avatar de l’utilisateur
Merci Stéphane d'avoir pris le temps d'expliquer tout cela, c'est très clair ;)


Haut
 Profil Envoyer un e-mail  
 
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 9 messages ] 

Heures au format UTC [ Heure d’été ]


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages
Vous ne pouvez pas joindre des fichiers

Rechercher:
Aller à:  
Abonnez-vous au flux RSS

Blog

Forum

Offres d'emploi

Copyright : Moteur, traduction et optimisation
Merci de votre visite sur le forum Oseox