Comment obtenir les 10 premières valeurs dans PostgreSQL?

257

J'ai une question simple:

J'ai une postgresqlbase de données: Scores(score integer).

Comment puis-je obtenir les 10 meilleurs scores le plus rapidement?

METTRE À JOUR:

Je ferai cette requête plusieurs fois et je vise la solution la plus rapide.

Joey Franklin
la source
6
-1: qu'as-tu fait jusqu'à présent? Pourquoi n'est-ce pas assez bon? Quelle est la version Postgres? O is est explain analyze?
mys

Réponses:

373

Pour cela, vous pouvez utiliser la limite

select *
from scores
order by score desc
limit 10

Si la performance est importante (quand ne l'est-elle pas ;-) recherchez un index sur le score.


À partir de la version 8.4, vous pouvez également utiliser le standard ( SQL: 2008 )fetch first

select *
from scores
order by score desc
fetch first 10 rows only

Comme l'a souligné @Raphvanns, cela vous donnera first 10 rowslittéralement. Pour supprimer les valeurs en double, vous devez sélectionner des distinctlignes, par exemple

select distinct *
from scores
order by score desc
fetch first 10 rows only

SQL Fiddle

Olaf Dietsche
la source
2
fetch first X rows onlyest la réponse que je cherchais - merci du futur lointain!
Mass Dot Net
36

Semble que vous recherchez ORDER BYdans l' DESCordre de fin avec la clause LIMIT :

SELECT
 *
FROM
  scores
ORDER BY score DESC
LIMIT 10

Bien sûr, cela SELECT *pourrait sérieusement affecter les performances, alors utilisez-le avec prudence.

Grzegorz Gierlik
la source
3

Notez que s'il y a des liens dans les 10 premières valeurs, vous n'obtiendrez que les 10 premières lignes, pas les 10 premières valeurs avec les réponses fournies. Ex: si les 5 premières valeurs sont 10, 11, 12, 13, 14, 15 mais que vos données contiennent 10, 10, 11, 12, 13, 14, 15, vous n'obtiendrez que 10, 10, 11, 12, 13, 14 comme votre top 5 avec unLIMIT

Voici une solution qui retournera plus de 10 lignes s'il y a des égalités mais vous obtiendrez toutes les lignes là où some_value_columnest techniquement dans le top 10.

select
  *
from
  (select
     *,
     rank() over (order by some_value_column desc) as my_rank
  from mytable) subquery
where my_rank <= 10
Raphvanns
la source
D'après sa question, il n'y a qu'une seule colonne dans le tableau. Alors pourquoi ne pas "sélectionner un score distinct dans l'ordre des scores par score desc limit 10"?
Derek
@Derek, bon point. Bien que ce ne soit probablement pas le cas dans une application du monde réel où nous cherchons généralement à identifier le top N de "quelque chose".
Raphvanns
Vrai. Je me concentre simplement sur sa question exacte. De plus, j'ai eu de la chance en utilisant limit dans une sous-requête comme la vôtre, par exemple "select * from table where value in (select distinct value from table order by value desc limit 10)". Je pense que c'est équivalent au vôtre. Je ne sais pas laquelle de nos requêtes fonctionnerait mieux, cela dépendrait probablement de la structure de la table et de l'indexation.
Derek
Il manque un mot clé après le rang ()
Tiago Alcobia
2
(SELECT <some columns>
FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date DESC
LIMIT 10)

UNION ALL

(SELECT <some columns>
FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date ASC    
LIMIT 10)
kashif
la source