SQL : regrouper des enregistrements

SQL : regrouper des enregistrements - SQL/NoSQL - Programmation

Marsh Posté le 09-12-2008 à 14:40:02    

Bonjour, mon problème est le suivant :

 

J'ai une table avec dedans des absences d'étudiants :


idAbsence  idProfs  idSuivre_semestre  idSeanceVt  dateDeclaration  Type  idCommente  Commentaire

 

Pour un même cours (idSeanceVt), un même étudiant (idSuivre_semestre) peut avoir plusieurs enregistrements  (par exemple il a été déclaré absent, puis finalement, absent justifié), bref.

 

Je voudrai faire une requete qui récupère toutes les absences d'un étudiant (idSuivre_semestre), les regroupe par séance (idSeanceVt) puis ne me garde que le dernier en date du regroupement (par séance donc).

 

Je pensais utiliser la clause "GROUP BY idSeanceVt", qui me regroupe bien les lignes par séance, mais je n'arrive pas  à choisir quel enregistrement il doit me renvoyer (il me renvoie toujours le 1er par id)...

 

J'ai tenté

SELECT *  FROM matable WHERE idSuivre_semestre=:idSuivre_Semestre GROUP BY idSeanceVt ORDER BY dateDeclaration DESC

mais ca ne marche pas :/

 

Merci d'avance !

Message cité 1 fois
Message édité par getget le 09-12-2008 à 14:41:30

---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 09-12-2008 à 14:40:02   

Reply

Marsh Posté le 09-12-2008 à 15:35:09    

ici : http://forum.hardware.fr/hfr/Progr [...] 9707_1.htm
Même problème que toi. Il a eu des réponses.


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
Reply

Marsh Posté le 09-12-2008 à 16:38:58    

getget a écrit :

Bonjour, mon problème est le suivant :
 
J'ai une table avec dedans des absences d'étudiants :


idAbsence  idProfs  idSuivre_semestre  idSeanceVt  dateDeclaration  Type  idCommente  Commentaire


 
Pour un même cours (idSeanceVt), un même étudiant (idSuivre_semestre) peut avoir plusieurs enregistrements  (par exemple il a été déclaré absent, puis finalement, absent justifié), bref.
 
Je voudrai faire une requete qui récupère toutes les absences d'un étudiant (idSuivre_semestre), les regroupe par séance (idSeanceVt) puis ne me garde que le dernier en date du regroupement (par séance donc).
 
Je pensais utiliser la clause "GROUP BY idSeanceVt", qui me regroupe bien les lignes par séance, mais je n'arrive pas  à choisir quel enregistrement il doit me renvoyer (il me renvoie toujours le 1er par id)...
 
J'ai tenté

SELECT *  FROM matable WHERE idSuivre_semestre=:idSuivre_Semestre GROUP BY idSeanceVt ORDER BY dateDeclaration DESC

mais ca ne marche pas :/
 
Merci d'avance !


 
 
C'est un compteur id _absence ?
 
Parce que je verrais bien un truc du genre
 
SELECT     id_suivresemestre, id_seance, type
FROM         matable
WHERE     (id_absence IN
                          (SELECT     MAX(id_absence)
                            FROM          matable
                            GROUP BY id_suivresemestre, id_seance))
GROUP BY id_suivresemestre, id_seance, type
 
 
comme ça par seance et élève tu as la dernière absence enregistrée....si ton id_absence est bien un compteur :D


---------------
I drive at 88mph ! Just in case...
Reply

Marsh Posté le 10-12-2008 à 04:54:32    

id_absence est une clé primaire auto incrémentée :)
Par contre, je dois pouvoir faire la même chose avec le dateDeclaration non ?  
 
Je vais tester ta soluce ;)
Le 2ème Group By est-il nécessaire ?


---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 10-12-2008 à 07:35:57    

getget a écrit :


Le 2ème Group By est-il nécessaire ?


cf le lien que j'ai donné  :sarcastic:


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
Reply

Marsh Posté le 10-12-2008 à 10:49:59    

getget a écrit :

id_absence est une clé primaire auto incrémentée :)
Par contre, je dois pouvoir faire la même chose avec le dateDeclaration non ?  
 
Je vais tester ta soluce ;)
Le 2ème Group By est-il nécessaire ?


 
 
Donc c'est bon, je suppose que tes évènements sont rentrés dans l'ordre, non ?
Si sur ta date_declaration tu ne gères pas l'heure précise, tu risques de te retrouver avec des doublons...
 
Les 2 group by sont nécessaires dans ma formule. Essaie de l'interpreter, tu comprendras.


---------------
I drive at 88mph ! Just in case...
Reply

Marsh Posté le 10-12-2008 à 10:51:53    

kao98 a écrit :


cf le lien que j'ai donné  :sarcastic:


 
 
Je ne vois pas vraiment en quoi ton lien répond à sa question ?  
 
Ptêt que j'ai pas compris sa question remarque  [:redlightneon]


---------------
I drive at 88mph ! Just in case...
Reply

Marsh Posté le 10-12-2008 à 10:56:16    

Le group by ! Dans un group by, il faut indiquer tous les champs du select !


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
Reply

Marsh Posté le 10-12-2008 à 11:00:30    

kao98 a écrit :

Le group by ! Dans un group by, il faut indiquer tous les champs du select !


 
 
J'avais même pas fait gaffe à son *  avant le group by  [:redlightneon]  
 


---------------
I drive at 88mph ! Just in case...
Reply

Marsh Posté le 10-12-2008 à 23:41:55    

kao98 a écrit :


cf le lien que j'ai donné  :sarcastic:


 
J'ai regardé ton lien, je n'y vois pas vraiment de rapport (et on peut, même si c'est mal, avec mysql >=4 ;))


---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 10-12-2008 à 23:41:55   

Reply

Marsh Posté le 10-12-2008 à 23:44:28    

chapi a écrit :


 
 
Donc c'est bon, je suppose que tes évènements sont rentrés dans l'ordre, non ?
Si sur ta date_declaration tu ne gères pas l'heure précise, tu risques de te retrouver avec des doublons...
 
Les 2 group by sont nécessaires dans ma formule. Essaie de l'interpreter, tu comprendras.


 
Je teste ce soir ;)
 
dateDeclaration est un champ datetime, peu de chance d'avoir un doublon :D


---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 11-12-2008 à 09:08:24    

chapi a écrit :


 
 
Donc c'est bon, je suppose que tes évènements sont rentrés dans l'ordre, non ?
Si sur ta date_declaration tu ne gères pas l'heure précise, tu risques de te retrouver avec des doublons...
 
Les 2 group by sont nécessaires dans ma formule. Essaie de l'interpreter, tu comprendras.


 
J'ai essayé d'interpréter ta requète, mais je ne comprends toujours pas l'intérêt du 2ème GROUP BY :/
 
Le 1er  (SELECT MAX(id_absence) FROM matable GROUP BY id_suivresemestre, id_seance) permet d'obtenir l'id_absence le plus grand pour chaque regroupement de séance, utilisé dans l'autre requète SELECT id_suivresemestre, id_seance, type FROM matable WHERE  (id_absence IN ...) GROUP BY id_suivresemestre, id_seance, type.
 
Puisque les données ont été regroupées par la 1ère et le resultat de cette requète utilisé dans le 2ème, je ne vois pas l'intérêtdu GROUP BY :/
 
Un

SELECT * FROM matable WHERE (idAbsence IN (SELECT MAX(idAbsence) FROM matable GROUP BY idSeanceVt, idSuivre_semestre) AND idSuivre_semestre=:idSuivre_semestre


 
me renvoie le bon résultat si executé dans phpMyAdmin.

Message cité 1 fois
Message édité par getget le 11-12-2008 à 09:34:08

---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 11-12-2008 à 09:32:01    

getget a écrit :


 
J'ai essayé d'interpréter ta requète, mais je ne comprends toujours pas l'intérêt du 2ème GROUP BY :/
 
Le 1er  (SELECT MAX(id_absence) FROM matable GROUP BY id_suivresemestre, id_seance) permet d'obtenir l'id_absence le plus grand pour chaque regroupement de séance, utilisé dans l'autre requète SELECT id_suivresemestre, id_seance, type FROM matable WHERE  (id_absence IN ...) GROUP BY id_suivresemestre, id_seance, type.
 
Puisque les données ont été regroupées par la 1ère et le resultat de cette requète utilisé dans le 2ème, je ne vois pas l'intérêtdu GROUP BY :/


 
 
T'as raison, il ne sert strictement à rien.  
J'avais dû mettre un aggregat dans ma premiere version et oublié de virer le group by.
 
Sorry, la prochaine fois je me relirai :D


---------------
I drive at 88mph ! Just in case...
Reply

Marsh Posté le 11-12-2008 à 09:35:06    

Pas grave, merci tout de même :jap:


---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 21-03-2009 à 01:40:36    

Bonjour, aujourd'hui je rencontre un nouveau soucis avec cette requête, les performances s'écroulent alors qu'il y a a peine 100 enregistrements dans la table :/
 
J'ai un peu farfouillé sur le net sur les performances de GROUP BY mais je n'a trouvé que 2/3 propositions, dont la création d'une table temporaire ...auriez vous d'autres solutions ?


---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 21-03-2009 à 02:10:03    

Certainement le IN qui plante les perf...! faut utiliser une jointure

Reply

Marsh Posté le 21-03-2009 à 02:14:55    

remplacer :
 
SELECT *  
FROM matable  
WHERE (
 idAbsence IN  
  (
  SELECT MAX(idAbsence)  
  FROM matable  
  GROUP BY idSeanceVt, idSuivre_semestre
  )  
 
par :
 
SELECT *  
FROM  matable A inner join  
 (
 SELECT MAX(idAbsence) as idAbsence
 FROM matable  
 GROUP BY idSeanceVt, idSuivre_semestre
 ) as B on A.idAbsence = B.idAbsence  
 
je ne pige pas le "AND idSuivre_semestre=:idSuivre_semestre", trop tard pour reflechir plus ! :)

Reply

Marsh Posté le 21-03-2009 à 02:24:30    

On peut joindre une table avec elle même ?


---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 21-03-2009 à 02:52:33    

Ca marche (avec un gain x3) :D


---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 21-03-2009 à 10:01:55    

getget a écrit :

Ca marche (avec un gain x3) :D


 
QQ regle d'or de la programmation SQL :
 - eviter les IN
 - NE JAMAIS UTILISER LES CURSEURS --> dans 99.9% un select est possible
 - eviter les jointure sur des colonnes de type char/varchar
 

Reply

Marsh Posté le 21-03-2009 à 14:23:32    

Merci bien !
Je vais essayer d'améliorer encore un peu le truc car le script met quand même 3s d'execution, c'est un poil longuet :/
 
Si je met une clause WHERE là ou il y a le GROUP BY, elle sera traitée avant ou après le regroupement ?


---------------
Gamertag : Getget94 - PSN : Getget1980 - Nintendo Network : Getget1980 - Uplau : Getget1980
Reply

Marsh Posté le 21-03-2009 à 21:57:05    

Evite le SELECT *
Ne récupère que les champs dont tu as besoin. Et si tu as besoin de tous les champs de la table, alors liste les tous.


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
Reply

Marsh Posté le 22-03-2009 à 01:18:51    

getget a écrit :

Merci bien !
Je vais essayer d'améliorer encore un peu le truc car le script met quand même 3s d'execution, c'est un poil longuet :/
 
Si je met une clause WHERE là ou il y a le GROUP BY, elle sera traitée avant ou après le regroupement ?


 
humm... bizarre ta question...
Le regroupement se fait sur le jeu de résultat renvoyé, donc logiquement la clause "where" est jouée avant.

Reply

Marsh Posté le 26-03-2009 à 13:04:02    

getget a écrit :

Merci bien !
Je vais essayer d'améliorer encore un peu le truc car le script met quand même 3s d'execution, c'est un poil longuet :/
 
Si je met une clause WHERE là ou il y a le GROUP BY, elle sera traitée avant ou après le regroupement ?


 
La clause WHERE s'exécute avant le regroupement.
 
Si tu veux rajouter un filtre sur le regroupement, il faut utiliser la clause "HAVING".
 
Par exemple : récupération des moyennes des salaires annuels par catégorie professionnelle supérieures à 30000€

Code :
  1. SELECT CATEGORIE_PRO,AVG(SALAIRE) as MOYENNE_SALAIRE
  2. FROM TABLE_INDIVIDU
  3. GROUP BY CATEGORIE_PRO
  4. HAVING AVG(SALAIRE) > 30000;


Message édité par Leif Erikson le 26-03-2009 à 13:04:14

---------------
Il n'est qu'une seule chose qui excite les animaux plus que le plaisir, et c'est la douleur.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed