Les réponses de @jjclarkson et @davethegr8 sont proches, mais vous ne pouvez pas mettre de fonctions d'agrégation dans la clause WHERE. La clause WHERE est évaluée pour chaque ligne.
Vous devez évaluer le MAX()
expression pour chaque groupe, vous devez donc utiliser un HAVING
clause.
Essayez ceci :
SELECT UserID
FROM ArrivalTimes
GROUP BY UserID
HAVING MAX(ArrivalTime) <= '09:00:00';
@MBCook commente que HAVING
peut être lent. Vous avez raison, ce n'est peut-être pas le moyen le plus rapide d'obtenir le résultat souhaité. Mais le HAVING
la solution est la plus claire . Dans certaines situations, les performances sont moins prioritaires que la clarté et la maintenabilité.
J'ai regardé la sortie EXPLAIN (sur MySQL 5.1.30) pour le HAVING
solution :aucun index n'a été utilisé et les notes supplémentaires indiquaient "Using temporary; Using filesort
," ce qui signifie généralement que les performances seront médiocres.
Considérez la requête suivante :
SELECT DISTINCT a1.UserID
FROM ArrivalTimes a1
LEFT OUTER JOIN ArrivalTimes a2
ON (a1.UserID = a2.UserID AND a2.ArrivalTime > '09:00:00')
WHERE a2.UserID IS NULL;
Cela génère un plan d'optimisation qui utilise un index sur UserID
et dit :
- a1 :"
Using index; Using temporary
" - a2 :"
Using where; Distinct
"
Enfin, la requête suivante génère un plan d'optimisation qui semble utiliser les index plus efficacement, et pas de tables temporaires ni de tri de fichiers.
SELECT DISTINCT a1.UserID
FROM ArrivalTimes a1
WHERE NOT EXISTS (SELECT * FROM ArrivalTimes a2
WHERE a1.UserID = a2.UserID
AND a2.ArrivalTime > '09:00:00');
- a1 :"
Using where; Using index
" - a2 :"
Using where
"
Cela semble le plus susceptible d'avoir les meilleures performances. Certes, je n'ai que quatre lignes dans ma table de test, donc ce n'est pas un test représentatif.