【问题标题】:Mysql get position of row after "sum" and "group"Mysql在“sum”和“group”之后获取行的位置
【发布时间】:2016-12-07 17:56:50
【问题描述】:

我需要以 2 种不同方式在 total_points 上获取此表中单个玩家 id 的位置(2 个单独的查询很好,除非它可以在 1 中完成?)

例如,如果 player_id = 1 - 我需要通过两种方式从总分中找出他们的行位置:

  1. 组合在一起并在 player_id 上求和(包括所有 season_id 和 guild_id)
  2. 将 player_id 与特定的 season_id(包括所有 guild_id)组合在一起并求和

.

+-----------+-----------+----------+--------------+
| player_id | season_id | guild_id | total_points |
+-----------+-----------+----------+--------------+
|         1 |         1 |        1 |            5 |
|         2 |         1 |        2 |            6 |
|         3 |         2 |        1 |            2 |
....
|         1 |         1 |        2 |            4 |
|         2 |         2 |        2 |            4 |
|         4 |         1 |        3 |            8 |
+-----------+-----------+----------+--------------+

所以在这个例子中我会说 player_id = 1 并且结果将返回到我的位置 2,因为他们有第二高的 SUM total_points 在这个例子中是 9(玩家 2 有 10)。

在另一个查询中,我需要将结果分组到一个 season_id 中。 player_id = 1 和 season_id = 1 应该返回位置 1,因为他们有 9,这是本赛季中最高的。

稍后我还需要通过 guild_id 限制它,但我想我可以弄清楚如果我得到一个使用 player_id 和 season_id 的查询

任何帮助都会很棒,所以我不必在 PHP 中完成所有这些工作并遍历所有数据库结果,如果可以在 MySQL 中完成,这将浪费资源,因为该表最终将有数百万条记录.

谢谢。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    我不确定它是否可以更短,但以下查询应该会给出您的要求:

    SELECT rank
    FROM (
        SELECT player_id, total_sum, @rank:=@rank+1 AS rank 
        FROM (
            SELECT player_id,  SUM(total_points) AS total_sum
            FROM players
            WHERE season_id=1 -- if you don't want to filter by season, remove this; or add more if you want to filter by other columns
            GROUP BY player_id
            ORDER BY total_sum DESC) AS sq, 
            (SELECT @rank:=0) AS tr
    ) AS q WHERE player_id = 1;
    

    查询说明

    在最深的子查询中,您计算​​所需数据的总点数:

    SELECT player_id,  SUM(total_points) AS total_sum
    FROM players
    WHERE season_id=1 -- if you don't want to filter by season, remove this; or add more if you want to filter by other columns
    GROUP BY player_id
    ORDER BY total_sum DESC
    

    您可以省略WHERE 或添加更多条件。最后一行显示您按总和降序排列,最高的在前。

    接下来使用上一个查询使用变量@rank计算排名:

    SELECT player_id, total_sum, @rank:=@rank+1 AS rank 
    FROM (
    ...) AS sq, 
    (SELECT @rank:=0) AS tr
    

    初始化:

    SELECT @rank:=0
    

    最后,通过这些数据,您可以选择您想知道的内容,例如player_id=1 的排名,如第一个查询所示。

    【讨论】:

    • 第三个 SELECT "player_id" 给出一个未知列错误。表名是“players”我试过players.player_id但同样的错误。
    • SELECT rank FROM ( SELECT player_id, total_sum, @rank:=@rank+1 AS rank FROM ( SELECT player_id, SUM(total_points) AS total_sum FROM players WHERE season_id=1 GROUP BY player_id ORDER BY total_sum DESC) AS sq, (SELECT @rank:=0) AS tr ) AS q WHERE player_id = 1; == '字段列表'中的未知列'player_id' 谢谢您的宝贵时间。
    • 开始测试子查询是否正常,然后用它来获取排名(示例的第二部分),最后从中过滤。我已经在我的一个数据库上测试了该查询,但是由于您没有在线发布示例(例如sqlfiddle.com),因此我无法在您的数据库上对其进行测试。
    • 我太傻了,我把错误的表名放在其他代码中太深了,以至于没有注意到明显的错误。感谢您的宝贵时间和帮助,非常感谢。
    • 别担心,这发生在我们所有人身上。很高兴能帮上忙。
    【解决方案2】:

    @agold 提供的解决方案是对的。

    这是另一个很好的解决方案:

    SELECT 
        player_id, 
        total_sum, 
        RANK() OVER(ORDER BY total_sum DESC) as rank
    FROM (
        SELECT 
            player_id, 
            SUM(total_points) AS total_sum
        FROM players
        WHERE season_id=1 -- optional filter
        GROUP BY player_id
        ORDER BY total_sum DESC
    ) AS sq;
    

    【讨论】:

      猜你喜欢
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多