ActiveRecord对子集或记录的计算

时间:2016-05-04 06:34:13

标签: ruby-on-rails ruby activerecord

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

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

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`

由于

4 个答案:

答案 0 :(得分:2)

试试这个:

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

答案 1 :(得分:0)

上述答案中的limit()失败

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

答案 2 :(得分:0)

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

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]]

Hack:注意points周围的双引号。这就是我如何设法强制执行sum参数的字面解释。没有它们,查询会引发一个"没有这样的列"错误。

答案 3 :(得分:-1)

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

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