我有一个带有以下型号的Rails应用程序:
用户拥有many_bets和Bets belongs_to User。每个投注都有一个Profitloss值,表示用户在该投注中赢了/输了多少。
因此,要计算特定用户赢得的总体数量,我会通过以下方式循环投注:
User.bets.sum(:profitloss)
我想向用户展示他与所有其他用户相比的排名,这可能看起来像这样:
"您的整体排名:第37位"
为此,我需要总结每位用户的总奖金,并找出当前用户的位置。
我该怎么做以及如何做,所以它不会使服务器过载:)
谢谢!
答案 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;