J'ai le tableau suivant:
id time text otheridentifier
-------------------------------------------
1 6 Apple 4
2 7 orange 4
3 8 banana 3
4 9 pear 3
5 10 grape 2
Ce que je veux faire est de sélectionner les 3 enregistrements les plus récents (par heure de desc), dont les otheridentifier
s sont distincts. Donc, dans ce cas, le résultat serait id
's: 5, 4 et 2.
id
= 3 serait ignoré car il existe un enregistrement plus récent avec le même champ otheridentifier
.
Voici ce que j'ai essayé de faire:
SELECT * FROM `table` GROUP BY (`otheridentifier`) ORDER BY `time` DESC LIMIT 3
Cependant, je finis par obtenir des rangées de id
= 5, 3 et 1 au lieu de 5, 4, 2 comme prévu.
Quelqu'un peut-il me dire pourquoi cette requête ne renvoie pas ce que j'attendais? J'ai essayé de changer ORDER BY en ASC, mais cela a simplement réorganisé les lignes retournées en 1, 3, 5.
Il ne renvoie pas ce que vous attendez, car le regroupement a lieu avant la commande, comme l'indique la position des clauses dans l'instruction SQL. Malheureusement, vous allez devoir être plus chic pour obtenir les rangs que vous voulez. Essaye ça:
SELECT *
FROM `table`
WHERE `id` = (
SELECT `id`
FROM `table` as `alt`
WHERE `alt`.`otheridentifier` = `table`.`otheridentifier`
ORDER BY `time` DESC
LIMIT 1
)
ORDER BY `time` DESC
LIMIT 3
Vous pouvez rejoindre la table sur elle-même pour filtrer la dernière entrée par otheridentifier
, puis prendre les 3 premières lignes de celle-ci:
SELECT last.*
FROM `table` last
LEFT JOIN `table` prev
ON prev.`otheridentifier` = last.`otheridentifier`
AND prev.`time` < last.`time`
WHERE prev.`id` is null
ORDER BY last.`time` DESC
LIMIT 3
J'avais une exigence similaire, mais j'avais des critères de sélection plus avancés. En utilisant certaines des autres réponses, je ne pouvais pas obtenir exactement ce dont j'avais besoin, mais j’ai trouvé que vous pouvez toujours faire un GROUP BY après et ORDER BY comme ceci:
SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t
GROUP BY t.otheridentifier
SELECT * FROM table t1
WHERE t1.time =
(SELECT MAX(time) FROM table t2
WHERE t2.otheridentifier = t1.otheridentifier)
La réponse d'Andomar est probablement meilleure car elle n'utilise pas de sous-requête.
Une approche alternative:
select *
from `table` t1
where t1.`time` in (
select max(s2.`time`)
from `table` t2
group by t2.otheridentifier
)
Vous pouvez utiliser cette requête pour obtenir la réponse correcte:
SELECT * FROM
(SELECT * FROM `table` order by time DESC)
t group by otheridentifier
qu'en est-il de
SELECT *, max(time) FROM `table` group by otheridentifier
Ça aussi:
SELECT * FROM
OrigTable T INNER JOIN
(
SELECT otheridentifier,max(time) AS duration
FROM T
GROUP BY otheridentifier) S
ON S.duration = T.time AND S.otheridentifier = T.otheridentifier.