SELECT MAX sur une colonne et DISTINCT sur une autre en SQL
Comment récupérer la valeur maximum pour un champ, et les valeurs distinctes pour un autre champ ? La fonction DISTINCT ne devra pas être utilisée. Explication.
Les fonctions sont des directives permettant de sélectionner une valeur en fonction de certains critères en SQL. On peut par exemple récupérer la valeur minimale ou maximale d'une colonne, la moyenne ou encore les différentes valeurs possibles.
Si utiliser une fonction seule est très simple, combiner entre elles différentes fonctions peut nécessiter plus de réflexion. Si l'on souhaite pour un champ récupérer les valeurs distinctes, puis sur un autre champ la valeur maximum, il sera nécessaire de bien réfléchir à la meilleure façon de procéder. Exemple de table livre :
id categorie date livre pages 1 | 10 | 04/03/2009 | livre A | 399 2 | 11 | 04/03/2009 | livre B | 244 5 | 12 | 04/03/2009 | livre C | 555 3 | 10 | 03/03/2009 | livre D | 300 4 | 11 | 03/03/2009 | livre E | 200 6 | 12 | 03/03/2009 | livre F | 500
On souhaite récupérer le livre ayant la date la plus récente par catégorie pour obtenir le résultat suivant :
1 | 10 | 04/03/2009 | livre A | 399 2 | 11 | 04/03/2009 | livre B | 244 5 | 12 | 04/03/2009 | livre C | 555
GROUP BY permet de regrouper les enregistrements en fonction des différentes valeurs d'un champ
Il faut donc pour cela utiliser les fonctions MAX, qui récupèrent la valeur maximum du champ date. Pour sélectionner les différentes catégories, la fonction DISTINCT ne fonctionnera pas car en la combinant à la fonction MAX, on obtiendrait des résultats incohérents. On utilise plutôt la clause GROUP BY qui permet de regrouper les enregistrements en fonction des différentes valeurs d'un champ.
La date la plus récente sera sélectionnée pour chaque catégorie. Pour récupérer les valeurs des autres champs correspondant aux enregistrements, il faut utiliser une jointure interne, qui reliera la requête de recherche avec une requête classique de sélection des champs de la table :
<p>SELECT l.* FROM livre l INNER JOIN ( SELECT categorie, MAX(date) AS maxDate FROM livre GROUP BY categorie ) groupel ON l.categorie = groupel.categorie AND l.date = groupel.maxDate</p>