Rails 寻求好的解决方案

ailen · 2015年09月07日 · 最后由 msg7086 回复于 2015年09月09日 · 1944 次阅读

大家好,现在遇到了这样一个问题: 有两个 model:

class User < ActiveRecord::Base
  has_many    :transfers
end

class Transfer < ActiveRecord::Base
  belongs_to  :user
end

然后 Transfer 里面有一个字段叫做coins是 integer 类型,现在需求是:按照 coins 从大到小排序并且 user_id 是唯一的的前 100 个 Transfer,有没有比较好的 query 方案?

自己好好翻翻 sql 的书就好了

你雇了一群农民工 (User),每天搬砖 (Transfer) 个数计做 coins,到月底你要统计一下单日搬砖前 100 名,要求一个农民工只能参加一次统计,所以他们会先找出自己单日搬砖最多的再去比咯。。

@pynix 这个思路是 ok 的,但是这样的话每个用户都要去运算,如果我直接通过 Transfer 的前 100 名,并且 user id 是唯一的岂不是省了很多事?

@nouse 问题就是当我选择比如 coins 为 distinct 的时候我还需要其他的 columns,但是这些 column 并不是 uniq 的

SELECT TOP 100 DISTINCT user_id, coins
FROM transfers
ORDER BY  coins DESC

问题是不是也可以这样描述:对每个用户 coins 最多的 Transfer 排序,取出前 100 的 Transfer(用户)?

首先,我不建议使用 raw SQL 做查询,最好使用scope,以便日后的代码重用。

比如,在 Transfer 中定义这样的scope

class Transfer < ActiveRecord::Base
  scope :max_coins, -> { select("max(coins) as max_coins") }
end

然后可以构造这样的查询:

User.joins(: transfers).merge(Transfer.max_coins).group("users.id").order("max_coins desc").limit(100).select("users.id")

试试看能不能得到你想要的结果。

@roclv 这个里面 user_id 和 coins 都是 distinct,如果 user_id 一样,coins 不一样,这样取出来的就是同一个用户的两条记录。但是我想要的是同一个用户的最高纪录

@yanhao 是的,不仅要用户,而且跟用户关联的最高的 Transfer 也要取出来

#6 楼 @yanhao 不知道能不能直接 include(:user)

#9 楼 @msg7086 我写的查询得到的结果就是 users,为什么还要include(:user)

#10 楼 @yanhao 诶看岔了以为是 Transfer 开始的。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号