144 votes

GROUP BY avec MAX (DATE)

J'ai un tableau montrant les trains avec leur destination et de l'heure de départ. Mon objectif est de dresser la liste la plus récente de destination (MAX heure de départ) pour chacun des trains.

Ainsi, par exemple, la table est

Train    Dest      Time
1        HK        10:00
1        SH        12:00
1        SZ        14:00
2        HK        13:00
2        SH        09:00
2        SZ        07:00

Le résultat souhaité doit être:

Train    Dest      Time
1        SZ        14:00
2        HK        13:00

J'ai essayé d'utiliser

SELECT Train, Dest, MAX(Time)
FROM TrainTable
GROUP BY Train

par j'ai eu un "ora-00979 pas un GROUPE PAR l'expression" erreur disant que je dois inclure 'Dest' dans mon groupe par déclaration. Mais sûrement que ce n'est pas ce que je veux...

Est-il possible de le faire en une seule ligne de SQL? (sous-requête est ok)

Merci beaucoup.

159voto

Thilo Points 108673
SELECT train, dest, time FROM ( 
  SELECT train, dest, time, 
    RANK() OVER (PARTITION BY train ORDER BY time DESC) dest_rank
    FROM traintable
  ) where dest_rank = 1

150voto

Oliver Hanappi Points 5141

Vous ne pouvez pas inclure dans votre jeu de résultats des colonnes non agrégées qui ne sont pas groupées. Si un train n'a qu'une seule destination, ajoutez simplement la colonne de destination à votre clause group by, sinon vous devez repenser votre requête.

Je pense que vous voulez savoir à quelle destination le train arrive le plus tard. Vous aurez besoin d'une sous-sélection. Par exemple:

 SELECT t.Train, t.Dest, r.MaxTime
FROM (SELECT Train, MAX(Time) as MaxTime
      FROM TrainTable
      GROUP BY Train) r
INNER JOIN Train t ON t.Train = r.Train AND t.Time = r.MaxTime
 

80voto

Joe Meyer Points 839

Voici un exemple qui utilise uniquement une jointure à gauche et, à mon avis, est plus efficace que n'importe quel groupe, par méthode: Blog ExchangeCore

 SELECT t1.*
FROM TrainTable AS t1 LEFT JOIN TrainTable AS t2
ON (t1.Dest = t2.Dest AND t1.Time < t2.Time)
WHERE t2.Time IS NULL;
 

13voto

Claudio Negri Points 11

Une autre solution:

 select * from traintable
where (train, time) in (select train, max(time) from traintable group by train);
 

9voto

Gary Myers Points 24819

Tant qu'il n'y a pas de doublons (et que les trains ont tendance à arriver dans une seule gare à la fois) ...

 select Train, MAX(Time),
      max(Dest) keep (DENSE_RANK LAST ORDER BY Time) max_keep
from TrainTable
GROUP BY Train;
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X