【问题标题】:SQL query to get the top "n" scores out of a listSQL查询从列表中获取前“n”个分数
【发布时间】:2010-09-07 10:54:57
【问题描述】:

我想找到不同的方法来解决我遇到的现实生活中的问题:想象有一场比赛或游戏,在此期间用户收集积分。您必须构建一个查询以显示具有最佳“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。实际上我解决了这个问题,但我认为有不同的方法可以获得结果......比我的更快或更有效。

【问题讨论】:

    标签: sql sql-server puzzle


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      这是一个有效的——我不知道它是否更有效,它是 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...”开始。

      【讨论】:

      • 我有一个类似的问题,正在尝试使用 MAX,然后我阅读了您的答案并记住了 DENSE_RANK。为我节省了很多时间。
      【解决方案3】:

      怎么样:

      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
      

      【讨论】:

        【解决方案4】:

        实际上对 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
        

        【讨论】:

          【解决方案5】:

          @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
          

          【讨论】:

            【解决方案6】:

            @Rob#37760:

            select top N points from users order by points desc
            

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

            【讨论】:

              【解决方案7】:

              @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 并且尚未经过测试。

              【讨论】:

                【解决方案8】:

                @马特·汉密尔顿

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

                【讨论】:

                  【解决方案9】:

                  Crucible 明白了(假设 SQL 2005 是一个选项)。

                  【讨论】:

                    【解决方案10】:

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

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

                    这将呈现前 5 个点

                    【讨论】:

                      【解决方案11】:

                      试试这个

                      select top N points from users order by points desc
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2015-03-28
                        • 2020-11-29
                        • 2022-01-08
                        • 2013-07-15
                        • 2017-06-05
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多