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

SQL sélectionne uniquement les lignes avec la valeur maximale sur une colonne

À première vue...

Tout ce dont vous avez besoin est un GROUP BY clause avec le MAX fonction d'agrégat :

SELECT id, MAX(rev)
FROM YourTable
GROUP BY id

Ce n'est jamais aussi simple, n'est-ce pas ?

Je viens de remarquer que vous avez besoin du content colonne également.

C'est une question très courante en SQL :trouver toutes les données de la ligne avec une valeur maximale dans une colonne par un identifiant de groupe. J'ai beaucoup entendu ça au cours de ma carrière. En fait, c'était l'une des questions auxquelles j'ai répondu lors de l'entretien technique de mon poste actuel.

C'est, en fait, si courant que la communauté Stack Overflow a créé une seule balise juste pour traiter des questions comme celle-ci : .

Fondamentalement, vous avez deux approches pour résoudre ce problème :

Joindre avec un simple group-identifier, max-value-in-group Sous-requête

Dans cette approche, vous trouvez d'abord le group-identifier, max-value-in-group (déjà résolu ci-dessus) dans une sous-requête. Ensuite, vous joignez votre table à la sous-requête avec égalité sur les deux group-identifier et max-value-in-group :

SELECT a.id, a.rev, a.contents
FROM YourTable a
INNER JOIN (
    SELECT id, MAX(rev) rev
    FROM YourTable
    GROUP BY id
) b ON a.id = b.id AND a.rev = b.rev

Joindre à gauche avec soi, peaufiner les conditions de jointure et les filtres

Dans cette approche, vous avez laissé rejoindre la table avec elle-même. L'égalité va dans le group-identifier . Ensuite, 2 gestes intelligents :

  1. La deuxième condition de jointure est d'avoir une valeur de gauche inférieure à la valeur de droite
  2. Lorsque vous effectuez l'étape 1, la ou les lignes qui ont réellement la valeur maximale auront NULL dans le côté droit (c'est un LEFT JOIN , rappelles toi?). Ensuite, nous filtrons le résultat joint, en affichant uniquement les lignes où le côté droit est NULL .

Donc, vous vous retrouvez avec :

SELECT a.*
FROM YourTable a
LEFT OUTER JOIN YourTable b
    ON a.id = b.id AND a.rev < b.rev
WHERE b.id IS NULL;

Conclusion

Les deux approches donnent exactement le même résultat.

Si vous avez deux lignes avec max-value-in-group pour group-identifier , les deux lignes seront dans le résultat dans les deux approches.

Les deux approches sont compatibles SQL ANSI et fonctionneront donc avec votre SGBDR préféré, quelle que soit sa "saveur".

Les deux approches sont également favorables aux performances, mais votre kilométrage peut varier (RDBMS, structure de base de données, index, etc.). Ainsi, lorsque vous choisissez une approche plutôt qu'une autre, benchmark . Et assurez-vous de choisir celui qui vous convient le mieux.