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

MySQL sélectionne les X meilleurs enregistrements pour chaque individu dans la table

Ce type de requête peut être reformulé dans un sens "plus grand-n-par-groupe", où vous voulez que les 10 meilleurs scores par "groupe" soient des valeurs de "foo".

Je vous suggère de jeter un œil à ce lien qui traite cette question à merveille, en commençant par une manière logique d'effectuer votre requête et en l'optimisant progressivement.

set @num := 0, @foo := '';
select foo, score
from (
   select foo, score,
      @num := if(@foo = foo, @num + 1, 1) as row_number,
      @foo := foo as dummy
  from tablebar
  where foo IN ('abc','def')
  order by foo, score DESC     
) as x where x.row_number <= 10;

Si vous vouliez effectuer cela sur tous niveaux de foo (c'est-à-dire imaginez faire un GROUP BY foo ), vous pouvez omettre le where foo in ... ligne.

Fondamentalement, la requête interne (SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC ) saisit foo et score à partir du tableau, en triant d'abord par foo puis score décroissant.

Le @num := ... augmente simplement chaque ligne, réinitialisant à 1 pour chaque nouvelle valeur de foo . C'est-à-dire @num est juste un numéro de ligne/rang (essayez d'exécuter la requête interne seule pour voir ce que je veux dire).

La requête externe sélectionne ensuite les lignes dont le numéro de rang/ligne est inférieur ou égal à 10.

REMARQUE :

Votre requête d'origine avec UNION supprime les doublons, donc si les 10 meilleurs scores pour foo='abc' sont tous 100 alors une seule ligne sera retournée (puisque le (foo,score) paire est répliquée 10 fois). Celui-ci renverra des doublons.