排名位置

时间:2012-09-30 19:49:06

标签: ruby-on-rails sum ranking

我有一个带有以下型号的Rails应用程序:

  • 用户
  • 赌注

用户拥有many_bets和Bets belongs_to User。每个投注都有一个Profitloss值,表示用户在该投注中赢了/输了多少。

因此,要计算特定用户赢得的总体数量,我会通过以下方式循环投注:

 User.bets.sum(:profitloss)

我想向用户展示他与所有其他用户相比的排名,这可能看起来像这样:

"您的整体排名:第37位"

为此,我需要总结每位用户的总奖金,并找出当前用户的位置。

我该怎么做以及如何做,所以它不会使服务器过载:)

谢谢!

3 个答案:

答案 0 :(得分:4)

您可以尝试与

类似的内容
User.join(:bets).
    select("users.id, sum(bets.profitloss) as accumulated").
    group("users.id").
    order("accumulated DESC")

然后在结果列表中搜索“用户”(不是真实用户,他们只有两个有意义的属性,他们的ID和带有总和的accumulated属性),对应于当前用户。

无论如何要获得单个用户的位置,您必须计算所有用户的accumulated,但至少这只是一个查询。更好的是,您可以在用户模型中存储累计值,并查询它以进行排名。

答案 1 :(得分:1)

如果您拥有大量用户和投注,您将无法“按需”计算和排序每个用户的全球利润损失,因此我建议您使用您安排的rake task定期(每天一次,每小时一次......)

position模型中添加列User,获取所有用户的列表,计算其全局利润损失,按利润损失对用户列表进行排序,最后更新position每个User的属性及其在列表中的位置。

答案 2 :(得分:1)

最好的方法是在user模型本身或与user具有1:1关系的单独模型上保留数据库中预先计算的总数。如果不这样做,则必须始终为所有用户计算总和以获得其评级,这意味着在bets表上进行全表操作。这就是说,这个查询会给你想要的结果,如果超过1个人有相同的总数,它将计入两个等级X:

select id, (select count(h.id) from users u inner join 
(select user_id, sum(profitloss) as `total` from bets group by user_id) b2
on b2.user_id = u.id, (select id from users) h inner join
(select user_id, sum(profitloss) as `total` from bets group by user_id) b 
on b.user_id = h.id where u.id = 1 and (b.total > b2.total)) 
as `rating` from users where id = 1;

您需要将user.id插入where id = X

中的查询中

如果您向user表添加一列以跟踪其总数,则查询会更简单一些,在此示例中,列名为total_profit_loss

select id, total_profit_loss, (select count(h.username)+1 from users u, 
(select username, score from users) h 
where id = 1 and (h.total_profit_loss > u.total_profit_loss)) 
as `rating` from users where id = 1;