【问题标题】:MySQL limit number of rows used to calculate the SUMMySQL 限制用于计算 SUM 的行数
【发布时间】:2019-09-06 10:56:50
【问题描述】:

我正在制作一个每小时计算玩家分数的游戏。需要分数,以便排行榜可以显示排名最高的玩家。游戏中赢得的“积分”存储在boards_played 表中。玩家表有一个 score 字段,每小时更新一次:

update players p 
       inner join (
          SELECT player_id, sum(points) as total 
            from boards_played
           where time_played > DATE_SUB(now(), INTERVAL 7 DAY)
           GROUP BY player_id) s on p.player_id = s.player_id
  set p.score = s.total

问题是,在 100 场比赛中总共赢得 50 分的人应该比在 200 场比赛中赢得 60 分的人排名更好。

简而言之,分数应仅基于您在过去 7 天内的最后 100 场比赛。

【问题讨论】:

  • 过去 100 场比赛或过去 7 天,或两者中的更低?
  • 是的,这两个条件都必须满足。因此,如果您在过去 7 天内只玩了 95 场比赛,那么您的分数只能从这 95 场比赛中计算出来。
  • ... 如果是 107 那么最近的 100?
  • 是的。它必须是最新的。

标签: mysql inner-join limit


【解决方案1】:

您可能在这里需要一个相关的子查询,以便为每个玩家检索正确的值。

要找到某个玩家的总分,这个子查询会做。

          SELECT SUM(points) as total
            FROM (
                   SELECT player_id, points
                     FROM boards_played
                    WHERE time_played > DATE_SUB(NOW(), INTERVAL 7 DAY)
                     AND player_id = ***something*** 
                    ORDER BY time_played DESC
                    LIMIT 100
                 ) a

现在,您需要将其合并到外部查询中

UPDATE players p
   SET score =
       (
          SELECT SUM(points) as total
            FROM (
                   SELECT points
                     FROM boards_played
                    WHERE time_played > DATE_SUB(NOW(), INTERVAL 7 DAY)
                      AND points.player_id = p.player_id 
                    ORDER BY time_played DESC
                    LIMIT 100
                 ) a
       )

为什么称为相关?子查询中的points.player_id = p.player_id将其与外部查询相关。这样做可以让LIMIT 分别应用于每个玩家的分数。

但是,您最好制作一个可以动态计算此值的视图,而不是更新您的表格。这样您就不必一直担心更新您的表格。它看起来像这样(未调试)。

CREATE VIEW players_with_score AS
SELECT p.player_id, p.col1, p.col2, p.col3,
       (  
          SELECT SUM(points) as total
            FROM (
                   SELECT points
                     FROM boards_played
                    WHERE time_played > DATE_SUB(NOW(), INTERVAL 7 DAY)
                      AND points.player_id = p.player_id 
                    ORDER BY time_played DESC
                    LIMIT 100
                 ) a
       ) score
  FROM player p 

然后你可以说像

  SELECT player_id, score
    FROM players_with_score
   WHERE score > 250

【讨论】:

  • 谢谢。我更喜欢查看选项。现在我接受你的回答,因为它看起来很有希望,而且我喜欢另一种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 2013-11-18
相关资源
最近更新 更多