Como obter os 10 principais valores no postgresql?

257

Eu tenho uma pergunta simples:

Eu tenho um postgresqlbanco de dados: Scores(score integer).

Como obter as 10 pontuações mais altas mais rapidamente?

ATUALIZAR:

Farei essa consulta várias vezes e estou buscando a solução mais rápida.

Joey Franklin
fonte
6
-1: o que você fez até agora? Por que isso não é bom o suficiente? Qual é a versão do Postgres? Onde está explain analyze?
22412

Respostas:

373

Para isso você pode usar limite

select *
from scores
order by score desc
limit 10

Se o desempenho é importante (quando não é ;-) procure um índice na pontuação.


A partir da versão 8.4, você também pode usar o padrão ( SQL: 2008 )fetch first

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

Como @Raphvanns apontou, isso lhe dará first 10 rowsliteralmente. Para remover valores duplicados, você deve selecionar distinctlinhas, por exemplo

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

SQL Fiddle

Olaf Dietsche
fonte
2
fetch first X rows onlyé a resposta que eu estava procurando - obrigado de um futuro distante!
Mass Dot Net
36

Parece que você está procurando ORDER BYem DESCordem final com a cláusula LIMIT :

SELECT
 *
FROM
  scores
ORDER BY score DESC
LIMIT 10

É claro que isso SELECT *pode afetar seriamente o desempenho, portanto, use-o com cautela.

Grzegorz Gierlik
fonte
3

Nota que, se há laços em top 10 valores, você só vai conseguir o top 10 linhas, e não os 10 principais valores com as respostas dadas. Ex: se os 5 principais valores forem 10, 11, 12, 13, 14, 15, mas seus dados contiverem 10, 10, 11, 12, 13, 14, 15, você receberá apenas 10, 10, 11, 12, 13, 14 como seu top 5 com umLIMIT

Aqui está uma solução que retornará mais de 10 linhas se houver empate, mas você obterá todas as linhas onde some_value_columnestá tecnicamente entre as 10 principais.

select
  *
from
  (select
     *,
     rank() over (order by some_value_column desc) as my_rank
  from mytable) subquery
where my_rank <= 10
Raphvanns
fonte
De sua pergunta, há apenas uma coluna na tabela. Então, por que não "selecionar uma pontuação distinta da ordem de pontuações por limite de pontuação 10"?
Derek
@ Derek, bom ponto. Embora isso provavelmente não seria o caso em um aplicativo do mundo real, onde geralmente procuramos identificar o N principal de "algumas coisas".
Raphvanns 20/02/19
Verdade. Apenas focando em sua pergunta exata. Além disso, tive boa sorte usando limit em uma subconsulta como a sua, por exemplo, "selecione * da tabela em que value in (selecione um valor distinto da ordem da tabela pelo valor desc limit 10)" Acho que isso é equivalente ao seu. Não tenho certeza de qual das nossas consultas teria melhor desempenho, provavelmente dependeria da estrutura e indexação da tabela.
Derek
Falta uma palavra-chave OVER após rank ()
Tiago Alcobia 04/06
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
fonte