ActiveRecord对子集或记录的计算

我有一个带有points属性的Game模型,我想计算前20个得分的总和。

我可以采取积分并让ruby计算总和,如:

 Game.order('points desc').limit(20).pluck(:points).sum 

但我很好奇是否有一种直接的方法让AR产生一个SQL聚合计算来实现同样的目的。 以下天真的尝试不起作用:

 Game.sum(:points, order: 'points desc', limit: 20) SELECT SUM(`games`.`points`) FROM `games` 

谢谢

试试这个:

  Game.order('points desc').limit(20).sum(:points) 

limit()在上面的答案中失败了

Game.order('point desc').limit(2).pluck(:point).inject(:+)

我将回答我自己的问题,但很乐意给出更好的解决方案。

sum函数实际上只接受一个参数,而AR 4.x用于简单地忽略任何额外的args,新的AR 5.0.0会引发错误。 最初的尝试确实是天真的。

按照@pitabas的建议,我尝试了:

 Game.order('points desc').limit(20).sum(:points) SELECT SUM("games"."points") FROM "games" LIMIT ? [["LIMIT", 20]] 

从AR构造的SQL可以看出,这也不起作用,因为LIMIT子句作用于查询的结果,该查询是单个值。 此外, ORDER子句完全被忽略。 对于所有记录,上述表达式的结果是points列的总和。

实际工作的SQL查询类似于:

 SELECT SUM(points) FROM (SELECT points FROM games ORDER BY points DESC LIMIT 20) 

我最接近的是以下内容:

 sq = Game.order('points desc').limit(20) Game.from(sq).sum('"points"') 

产量:

 SELECT SUM("points") FROM (SELECT "games".* FROM "games" ORDER BY points desc LIMIT ?) subquery [["LIMIT", 20]] 

哈克:注意points周围的双引号。 这就是我设法强制执行sum参数的字面解释的方法。 没有它们,查询会引发“无此列”错误。

请注意,如果您只想计算总和,那么在订购结果时没有意义,那么下面的回答就足够了

Game.limit(10).sum(:points)