Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 23/08/2011, 15h59   #1
Modérateur
 
Avatar de sebhm
 
Homme Seb
Développeur Web
Inscription : avril 2004
Messages : 1 063
Détails du profil
Informations personnelles :
Nom : Homme Seb
Âge : 31
Localisation : France, Landes (Aquitaine)

Informations professionnelles :
Activité : Développeur Web
Secteur : Agroalimentaire - Agriculture

Informations forums :
Inscription : avril 2004
Messages : 1 063
Points : 1 181
Points : 1 181
Par défaut group by et max

Bonjour,

j'ai une table 'ma_table' qui ressemble à ceci :

Code :
1
2
3
4
5
6
7
8
ID_ma_table    id_user   date_heure   une_valeur
1             1          15/05 4h          valeur_1
2             1          22/05 3h          valeur_2
3             1          05/04 1h          valeur_4
4             2          22/05 7h          valeur_1
5             2          05/04 1h          valeur_2
6             3          12/05 8h          valeur_5
7             3          25/06 3h          valeur_6

je souhaite recuperer le dernier enregistrement (donc selon le champ 'date_heure') par user.
A priori rien de compliquer mais ca fait 2 heures que j'arrive à rien.

je voudrais donc avoir comme resultat
Code :
1
2
3
4
id_user     date_heure       une_valeur
1           22/05 3h           valeur_2
2           22/05 7h           valeur_1
3           25/06 3h           valeur_6
si je fais
Code :
1
2
3
SELECT id_user, MAX(date_heure) AS heure, une_valeur
FROM ma_table
GROUP BY id_user
j'ai
Code :
1
2
3
4
id_user     date_heure       une_valeur
1           22/05 3h           valeur_4
2           22/05 7h           valeur_2
3           25/06 3h           valeur_6
le champ 'une_valeur' retourné n'est pas bon. Il prend le dernier qu'il trouve sans rapport avec MAX(date_heure)

la solution que j'ai trouvée me semble complexe :
Code :
1
2
3
4
5
6
7
8
9
SELECT id_user, date_heure, une_valeur
FROM ma_table T1
INNER JOIN (
  SELECT id_user, MAX(date_heure) AS heure
  FROM ma_table
  GROUP BY id_user
) T2
ON T1.id_user = T2.id_user
AND t1.date_heure=T2.heure
N'y a-t-il pas plus simple que cela ?

De plus, cette requete me retourne plusieurs enregistrements pour un meme id_user si date_heure revient plusieurs fois.
Par exemple
Code :
1
2
3
4
5
6
7
8
ID_ma_table    id_user   date_heure   une_valeur
1             1          15/05 4h          valeur_1
2             1          22/05 3h          valeur_2
3             1          25/05 3h          valeur_4
4             2          22/05 7h          valeur_1
5             2          05/04 1h          valeur_2
6             3          12/05 8h          valeur_5
7             3          25/06 3h          valeur_6
va me donner
Code :
1
2
3
4
5
id_user     date_heure       une_valeur
1           22/05 3h           valeur_2
1           22/05 3h           valeur_4
2           22/05 7h           valeur_1
3           25/06 3h           valeur_6
alors que je n'en veux qu'un seul (à la limite trié selon l'ID_ma_table)

merci de votre aide
sebhm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/08/2011, 16h13   #2
Membre éclairé
 
Avatar de Rei Angelus
 
Homme
Ingénieur développement logiciels
Inscription : mars 2006
Messages : 291
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 35
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : mars 2006
Messages : 291
Points : 314
Points : 314
__________________
Je ne sais qu'une chose, c'est que je ne sais rien. (Socrate)
Rei Angelus est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/08/2011, 16h35   #3
Modérateur
 
Avatar de al1_24
 
Homme Alain
Ingénieur d'études décisionnel
Inscription : mai 2002
Messages : 4 446
Détails du profil
Informations personnelles :
Nom : Homme Alain
Âge : 51
Localisation : France, Val de Marne (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études décisionnel
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 4 446
Points : 7 543
Points : 7 543
En partant de ta requête, il faut sélectionner le plus petit ID_TABLE pour chaque couple ID_USER, HEURE, ce qui donne :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SELECT  id_user
    ,   date_heure
    ,   une_valeur
FROM    ma_table T1
    INNER JOIN 
        (   SELECT  id_user
                ,   heure
                ,   MIN(id_table) AS id_table
            FROM    (   SELECT  id_user
                            ,   MAX(date_heure) AS heure
                        FROM    ma_table
                        GROUP BY id_user
                    ) T2
            GROUP BY id_user
                ,   heure
        )   T3
        ON  T1.id_table = T3.id_table
;
qui peut aussi s'écrire comme cela :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SELECT  id_user
    ,   date_heure
    ,   une_valeur
FROM    ma_table T1
WHERE   EXISTS 
        (   SELECT  1
            FROM    ma_table T2
            WHERE   EXISTS
                    (   SELECT  1
                        FROM    ma_table T3
                        WHERE   T2.id_user    = T3.id_user
                        HAVING  T2.date_heure = MAX(date_heure)
                    ) T2
            WHERE   T1.id_user  = T2.id_user
            HAVING  T1.id_table = MIN(T2.id_table)
        )
;
__________________
Modérateur Langage SQL
Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
N'oubliez pas le bouton et pensez aux balises [code]
Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
al1_24 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/08/2011, 21h42   #4
Modérateur
 
Avatar de sebhm
 
Homme Seb
Développeur Web
Inscription : avril 2004
Messages : 1 063
Détails du profil
Informations personnelles :
Nom : Homme Seb
Âge : 31
Localisation : France, Landes (Aquitaine)

Informations professionnelles :
Activité : Développeur Web
Secteur : Agroalimentaire - Agriculture

Informations forums :
Inscription : avril 2004
Messages : 1 063
Points : 1 181
Points : 1 181
merci pour ta réponse.
Je n'ai pas tout compris à ta seconde requete, mais je vais m'y pencher des que possible !

pour la premiere
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SELECT  id_user
    ,   date_heure
    ,   une_valeur
FROM    ma_table T1
    INNER JOIN 
        (   SELECT  id_user
                ,   heure
                ,   MIN(id_table) AS id_table
            FROM    (   SELECT  id_user
                            ,   MAX(date_heure) AS heure
                        FROM    ma_table
                        GROUP BY id_user
                    ) T2
            GROUP BY id_user
                ,   heure
        )   T3
        ON  T1.id_table = T3.id_table
;
il me dit "id_table inconnu"
normal car id_table n'est pas dans T2.
Et le probleme si je l'ajoute est que ce n'est pas l'id_table correspondant à MAX(date_heure) qui est retourné
sebhm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/08/2011, 23h36   #5
Modérateur
 
Avatar de al1_24
 
Homme Alain
Ingénieur d'études décisionnel
Inscription : mai 2002
Messages : 4 446
Détails du profil
Informations personnelles :
Nom : Homme Alain
Âge : 51
Localisation : France, Val de Marne (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études décisionnel
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 4 446
Points : 7 543
Points : 7 543
Tu as tout as fait raison, j'ai voulu simplifier et j'ai retiré une partie importante
Voilà la bonne requête :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT  t1.id_user
    ,   t1.date_heure
    ,   t1.une_valeur
FROM    ma_table t1
    INNER JOIN 
        (   SELECT  t2.id_user
                ,   t2.date_heure
                ,   MIN(t2.id_table) AS id_table
            FROM    ma_table T2
                INNER JOIN 
                    (   SELECT  id_user
                            ,   MAX(date_heure) AS date_heure
                        FROM    ma_table
                        GROUP BY id_user
                    )   t3
                    ON  t2.id_user    = t3.id_user
                    AND t2.date_heure = t3.date_heure 
            GROUP BY t2.id_user
                ,   t2.date_heure
        )   t4
        ON  t1.id_table = t4.id_table
;
Avec les excuses les plus plates...
__________________
Modérateur Langage SQL
Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
N'oubliez pas le bouton et pensez aux balises [code]
Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
al1_24 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/08/2011, 09h03   #6
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 641
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 641
Points : 2 634
Points : 2 634
Bonjour,


Selon votre SGBD vous pouvez aussi utiliser les fonctions de fenêtrages.

Ceci aura l'avantage de ne faire qu'un seul scan de table ... à tester et comparer pour les perfs.

Code :
1
2
3
4
5
6
7
8
9
 
WITH tmp AS (
SELECT id_user, date_heure, une_valeur, 
  row_number() over(partition BY id_user ORDER BY date_heure DESC, id_table) AS rnk
FROM ma_table)
 
SELECT id_user, date_heure, une_valeur
FROM tmp
WHERE rnk = 1
punkoff est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/08/2011, 09h33   #7
Modérateur
 
Avatar de sebhm
 
Homme Seb
Développeur Web
Inscription : avril 2004
Messages : 1 063
Détails du profil
Informations personnelles :
Nom : Homme Seb
Âge : 31
Localisation : France, Landes (Aquitaine)

Informations professionnelles :
Activité : Développeur Web
Secteur : Agroalimentaire - Agriculture

Informations forums :
Inscription : avril 2004
Messages : 1 063
Points : 1 181
Points : 1 181
@al1_24
merci beaucoup ca fonctionne nickel
(je pensais quand meme qu'on pouvait faire plus simple car la problematique ne semblait pas élevée, mais tant pis, je vais m'en remettre )

@punkoff
je suis sous MySQL qui ne veut pas entendre parler de cette syntaxe (ou alors j'ai pas fait ce qu'il fallait )
sebhm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/08/2011, 10h03   #8
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 641
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 641
Points : 2 634
Points : 2 634
MtySql ne supporte pas ce type de requête.
punkoff est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 16h42.


 
 
 
 
Partenaires

Hébergement Web