Pergunta

Gostaria de encontrar diferentes maneiras de resolver um problema da vida real que tive:imagine ter um concurso, ou um jogo, durante o qual os usuários acumulam pontos.Você deve criar uma consulta para mostrar a lista de usuários com as melhores pontuações “n”.

Estou dando um exemplo para esclarecer.Digamos que esta seja a tabela de Usuários, com os pontos ganhos:

UserId - Points
1      - 100
2      -  75
3      -  50
4      -  50
5      -  50
6      -  25

Se eu quiser as 3 primeiras pontuações, o resultado será:

UserId - Points
1      - 100
2      -  75
3      -  50
4      -  50
5      -  50

Isso pode ser realizado em uma visualização ou procedimento armazenado, conforme você desejar.Meu banco de dados de destino é o SQL Server.Na verdade resolvi isso, mas acho que existem diferentes maneiras de obter o resultado ...mais rápido ou mais eficiente que o meu.

Foi útil?

Solução

Não testado, mas deve funcionar:

select * from users where points in
(select distinct top 3 points from users order by points desc)

Outras dicas

Aqui está um que funciona - não sei se é mais eficiente e é o SQL Server 2005+

with scores as (
    select 1 userid, 100 points
    union select 2, 75
    union select 3, 50
    union select 4, 50
    union select 5, 50
    union select 6, 25
),
results as (
    select userid, points, RANK() over (order by points desc) as ranking 
    from scores
)
select userid, points, ranking
from results
where ranking <= 3

Obviamente, o primeiro "com" é configurar os valores, para que você possa testar o segundo com e selecionar o trabalho final - você poderia começar com "com resultados como..." se estivesse consultando uma tabela existente.

Que tal:

select top 3 with ties points 
from scores
order by points desc

Não tenho certeza se "com vínculos" funciona em qualquer outra coisa no SQL Server.

No SQL Server 2005 e superior, você pode passar o número "top" como um parâmetro int:

select top (@n) with ties points 
from scores
order by points desc

Na verdade uma modificação no WHERE IN, utilizando um INNER JOIN será muito mais rápida.

SELECT 
   userid, points 
FROM users u
INNER JOIN 
(
   SELECT DISTINCT TOP N 
      points 
   FROM users 
   ORDER BY points DESC
) AS p ON p.points = u.points

@bosnic, não acho que funcionará conforme solicitado, não estou muito familiarizado com o MS SQL, mas esperaria que ele retornasse apenas 3 linhas e ignorasse o fato de que 3 usuários estão empatados no 3º lugar.

Algo assim deve funcionar:

select userid, points 
   from scores 
   where points in (select top 3 points 
                       from scores 
                       order by points desc) 
   order by points desc

@Rob#37760:

select top N points from users order by points desc

Esta consulta selecionará apenas 3 linhas se N for 3, veja a pergunta."Top 3" deve retornar 5 linhas.

@Espo, obrigado pela verificação da realidade - adicionou a subseleção para corrigir isso.

Acho que a resposta mais fácil é:

select userid, points from users
where points in (select distinct top N points from users order by points desc) 

Se você quiser colocar isso em um processo armazenado que usa N como parâmetro, você terá que ler o SQL em uma variável e executá-lo ou executar o truque de contagem de linhas:

declare @SQL nvarchar(2000)
set @SQL = "select userID, points from users "
set @SQL = @SQL + " where points in (select distinct top " + @N
set @SQL = @SQL + " points from users order by points desc)"

execute @SQL

ou

SELECT  UserID, Points
FROM     (SELECT  ROW_NUMBER() OVER (ORDER BY points DESC)
         AS Row, UserID, Points FROM Users)
        AS usersWithPoints
WHERE  Row between 0 and @N

Ambos os exemplos assumem o SQL Server e não foram testados.

@Matt Hamilton

Sua resposta funciona com o exemplo acima, mas não funcionaria se o conjunto de dados fosse 100, 75, 75, 50, 50 (onde retornaria apenas 3 linhas).TOP COM TIES inclui apenas os empates da última linha retornada...

O Crisol entendeu (assumindo que o SQL 2005 seja uma opção).

Ei, encontrei todas as outras respostas um pouco longas e ineficientes, minha resposta seria:

select * from users order by points desc limit 0,5

isso renderá os 5 primeiros pontos

Experimente isso

select top N points from users order by points desc
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top