Consulta SQL para obter as melhores “n” pontuações de uma lista
-
09-06-2019 - |
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.
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