7

我想找到解决我遇到的现实生活问题的不同方法:想象有一场比赛或游戏,在此期间用户收集积分。您必须构建一个查询以显示具有最佳“n”分数的用户列表。

我正在做一个例子来澄清。假设这是用户表,获得的积分:

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

如果我想要前 3 名,结果将是:

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

这可以根据需要在视图或存储过程中实现。我的目标数据库是 Sql Server。实际上我解决了这个问题,但我认为有不同的方法来获得结果......比我的更快或更有效。

4

11 回答 11

11

未经测试,但应该可以工作:

select * from users where points in
(select distinct top 3 points from users order by points desc)
于 2008-09-01T11:07:41.993 回答
4

这是一个有效的-我不知道它是否更有效,它是 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

显然,第一个“with”是设置值,因此您可以测试第二个 with,最后选择工作 - 如果您正在查询现有表,您可以从“with results as...”开始。

于 2008-09-01T11:59:05.537 回答
1

怎么样:

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

不确定“with ties”是否适用于 SQL Server 以外的任何东西。

在 SQL Server 2005 及更高版本上,您可以将“top”数字作为 int 参数传递:

select top (@n) with ties points 
from scores
order by points desc
于 2008-09-01T11:32:25.913 回答
1

实际上,对 WHERE IN 的修改,使用 INNER JOIN 会快得多。

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
于 2008-09-18T01:57:27.880 回答
0

@bosnic,我认为这不会按要求工作,我对 MS SQL 不太熟悉,但我希望它只返回 3 行,并忽略 3 个用户并列第三名的事实。

像这样的东西应该工作:

select userid, points 
   from scores 
   where points in (select top 3 points 
                       from scores 
                       order by points desc) 
   order by points desc
于 2008-09-01T11:12:00.377 回答
0

@Espo 感谢您的实际检查 - 添加了子选择来纠正它。

我认为最简单的回应是:

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

如果你想把它放在一个以 N 作为参数的存储过程中,那么你要么必须将 SQL 读入一个变量然后执行它,要么执行行计数技巧:

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

或者

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

这两个示例都假定 SQL Server 并且尚未经过测试。

于 2008-09-01T11:15:53.630 回答
0

@Rob#37760:

select top N points from users order by points desc

如果 N 为 3,此查询将仅选择 3 行,请参阅问题。“前 3 名”应返回 5 行。

于 2008-09-01T11:21:20.073 回答
0

@马特汉密尔顿

您的答案适用于上面的示例,但如果数据集为 100、75、75、50、50(它只会返回 3 行),则该答案将不起作用。TOP WITH TIES 仅包括返回的最后一行的关系...

于 2008-09-01T13:02:31.673 回答
0

Crucible 得到了它(假设 SQL 2005 是一个选项)。

于 2008-09-01T13:08:10.783 回答
0

试试这个

select top N points from users order by points desc
于 2008-09-19T10:03:48.797 回答
0

嘿,我发现所有其他答案都有点长而且效率低我的答案是:

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

这将呈现前 5 分

于 2013-11-01T06:34:32.503 回答