Mysql
 sql >> Base de données >  >> RDS >> Mysql

Sélectionnez dans MySQL où toutes les lignes remplissent une condition

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.