Odpowiedzi z @jjclarkson i @davethegr8 są bliskie, ale nie możesz umieścić funkcji agregujących w klauzuli WHERE. Klauzula WHERE jest oceniana dla każdego wiersza.
Musisz ocenić MAX()
wyrażenie dla każdej grupy, więc musisz użyć HAVING
klauzula.
Spróbuj tego:
SELECT UserID
FROM ArrivalTimes
GROUP BY UserID
HAVING MAX(ArrivalTime) <= '09:00:00';
@MBCook komentarze, które HAVING
może być powolny. Masz rację, może to nie być absolutnie najszybszy sposób na uzyskanie pożądanego rezultatu. Ale HAVING
rozwiązanie jest jasne . Są sytuacje, w których wydajność ma niższy priorytet niż przejrzystość i łatwość konserwacji.
Spojrzałem na wyjście EXPLAIN (w MySQL 5.1.30) dla HAVING
rozwiązanie:nie użyto żadnych indeksów, a dodatkowe uwagi mówiły „Using temporary; Using filesort
”, co zwykle oznacza, że wydajność będzie niska.
Rozważ następujące zapytanie:
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;
Spowoduje to wygenerowanie planu optymalizacji, który używa indeksu na UserID
i mówi:
- a1:"
Using index; Using temporary
- a2:"
Using where; Distinct
"
Na koniec następująca kwerenda generuje plan optymalizacji, który wydaje się najefektywniej wykorzystywać indeksy, bez tabel tymczasowych ani sortowania plików.
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
”
Wydaje się, że najprawdopodobniej będzie to miało najlepszą wydajność. Muszę przyznać, że w mojej tabeli testowej są tylko cztery wiersze, więc nie jest to test reprezentatywny.