Ruby on rails 活动记录使用不同的where语句减去两个值?

Ruby on rails 活动记录使用不同的where语句减去两个值?,ruby-on-rails,ruby,Ruby On Rails,Ruby,我一直试图用正确的方法来解决这个问题。我有两张桌子,一张是和dailystats桌子有一对多关系的球员。每天都会记录新的统计数据。我只想拿下那个月的最高统计数据,但这些数据都是记录在案的。所以今天的统计数据是所有月份的总和。所以我需要取当前月份,从上个月的最后一天减去它 我使用下面的数据来获取当天的最新统计数据 @gamesplayed = Player.joins(:dailystats).select('players.*, dailystats.gamesplayed AS average

我一直试图用正确的方法来解决这个问题。我有两张桌子,一张是和dailystats桌子有一对多关系的球员。每天都会记录新的统计数据。我只想拿下那个月的最高统计数据,但这些数据都是记录在案的。所以今天的统计数据是所有月份的总和。所以我需要取当前月份,从上个月的最后一天减去它

我使用下面的数据来获取当天的最新统计数据

@gamesplayed = Player.joins(:dailystats).select('players.*, dailystats.gamesplayed AS average_score').order('average_score desc').group('players.id').where('MONTH(statdate) = MONTH(NOW())').first.name
那么,从这个月——上个月的差异来看,我将如何为顶级球员做到这一点呢?我想应该是这样的

@gamesplayed = (Player.joins(:dailystats).select('players.*, dailystats.gamesplayed AS average_score').where('(MONTH(statdate) = MONTH(NOW()))') -  Player.joins(:dailystats).select('players.*, dailystats.gamesplayed AS average_score').where('(MONTH(statdate) = MONTH(NOW() - INTERVAL 1 MONTH)')).first.name

您可以运行两个查询,就像您建议的解决方案一样,但是
-
操作符显然不够聪明,无法处理每一个查询的行差异。您必须编写自己的代码来迭代每个“this month”行,找到相应的“last month”行,并存储差异

但您也可以在一个查询中完成此操作。在Rails的查询语法中这样做会变得很复杂,因为我们在这里讨论的是相对高级的SQL,但我会尽我所能

Player
  .joins("JOIN (SELECT player_id,
            SUM(gamesplayed) as gamesplayed, COUNT(*) as count
            FROM dailystats
            WHERE DATE_TRUNC('MONTH', statdate) = DATE_TRUNC('MONTH', NOW())
            GROUP BY player_id) this_month
          ON this_month.player_id = players.id 
        ")
  .joins("JOIN (SELECT player_id,
            SUM(gamesplayed) as gamesplayed, COUNT(*) as count
            FROM dailystats
            WHERE DATE_TRUNC('MONTH', statdate) = 
              DATE_TRUNC('MONTH', NOW() - INTERVAL '1 month')
            GROUP BY player_id) last_month
          ON last_month.player_id = players.id 
        ")
   .select('players.*')
   .select('this_month.gamesplayed - last_month.gamesplayed AS gamesplayed_change')
(您可能会注意到我将您的
MONTH()
用法更改为
DATE\u TRUNC('MONTH')
;原因是MONTH将返回1、2、3、4等,这意味着如果您的站点运行时间超过一年,您将开始不适当地返回去年的数据。)

上述工作方式是连接到dailystats表两次;本月统计数据一次,上月统计数据一次。然而,由于每个玩家都有多个dailystats条目,我们首先通过子查询对每个月的统计数据进行分组,这样我们希望每个玩家只加入一行这样的数据。然后,我们的SELECT子句可以使用上面计算的每月统计数据来获得合理的差异

现在,上面的代码太长,无法直接放入您的代码库中。要清理它,您可能需要创建monthlystats汇总表(可以作为数据库中的视图实现),或者将代码转换为使用原始SQL(提取到单独的模块)


另外,上述代码未经测试,因此可能包含一两个错误。如果不起作用,请发表评论,我将帮助解决。

您的解决方案不起作用,或者您正在寻求更好的解决方案?对于后者,更改数据存储方式将使其成为优化的单个查询。如果您存储的是增量更改,而不是累积更改,那么将更容易检索。