2008-09-01 24 views
6

Me gustaría encontrar las diferentes formas de resolver un problema de la vida real que tenía: imagina tener un concurso, o un juego, durante el cual los usuarios recolectan puntos. Debe crear una consulta para mostrar la lista de usuarios con los mejores puntajes "n".Consulta SQL para obtener los primeros puntajes "n" de una lista

Estoy haciendo un ejemplo para aclarar. Digamos que esta es la tabla de usuarios, con los puntos ganados:

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

Si quiero los 3 mejores puntuaciones, el resultado será:

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

Esto se puede realizar en una vista o una procedimiento almacenado, como quieras. Mi destino db es Sql Server. En realidad, resolví esto, pero creo que hay diferentes formas de obtener el resultado ... más rápido o más eficiente que el mío.

Respuesta

9

no probado, pero debería funcionar:

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

@bosnic, yo no creo que funcione conforme a lo solicitado, no estoy tan familiarizado con MS SQL, pero yo esperaría que vuelva sólo 3 filas , e ignore el hecho de que 3 usuarios están empatados en el 3er lugar.

Algo como esto debería funcionar:

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

@Espo gracias por la revisión de la realidad - añadió la sub-select para corregir eso.

creo que la respuesta más sencilla es:

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

Si desea poner esto en un procedimiento almacenado que tiene N como parámetro, a continuación, ya sea que usted tiene que hacer leer el código SQL en una variable luego ejecutarlo, o hacer el truco número de filas:

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 

o

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 ejemplos asumen SQL Server y no se han probado.

0

@ Rob # 37760:

select top N points from users order by points desc 

Esta consulta sólo seleccionará 3 filas si N es 3, ver la pregunta. "Top 3" debería devolver 5 filas.

1

¿Qué tal:

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

No estoy seguro si "con lazos" funciona en otra cosa SQL Server.

En SQL Server 2005 y arriba, puede pasar el número "superior" como un parámetro int:

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

Aquí hay una que funciona - No sé si es más eficiente, y es de 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, la primera "a" es la creación de los valores, por lo que puede probar con la segunda, y última de selección de trabajo - usted podría comenzar en "con resultados como ..." si usted fuera consultar contra una tabla existente.

+0

Tengo un problema similar y estaba tratando de usar MAX y luego leí su responde y recuerda DENSE_RANK. Me ahorro mucho tiempo. – DataGirl

0

@ Matt Hamilton

Su respuesta trabaja con el ejemplo anterior, pero no funcionaría si el conjunto de datos fue de 100, 75, 75, 50, 50 (en el que volvería a sólo 3 filas). TOP WITH TIES solo incluye los enlaces de la última fila devuelta ...

0

Crucible lo consiguió (suponiendo que SQL 2005 sea una opción).

0

En realidad, una modificación de WHERE IN, que utiliza INNER JOIN será mucho más 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 
0

probar este

select top N points from users order by points desc 
0

Hey Me pareció que todos los demás respuestas poco largo e ineficiente Mi respuesta sería:

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

esto hará que los 5 primeros puntos

Cuestiones relacionadas