我有一个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`
由于
答案 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)