我见过类似的问题,但没有完全符合我需要的答案。如果它在那里,我还没有看到它。我在Rails 3.1,Ruby 1.9.2上,部署在Heroku Cedar堆栈上(所以我使用的是postgres)
我有这个型号:
class User
has_many :orders
end
class Order
belongs_to :user
#scope :last_for_each_user, ???
#scope :first_for_each_user, ???
end
我需要范围(或方法)返回所有用户的第一个订单的所有订单,以及所有用户的最后订单的所有订单。我的第一直觉是使用GROUP BY,它适用于:SQLite3中的last_for_each_user,但Postgres不允许您选择不在GROUP BY子句中或作为聚合函数的一部分选择的列,我需要完全形成的订单对象(即所有列,订单。*)。
有什么想法吗?我不想选择整个表并在Ruby中对其进行排序。这感觉不对,在记忆中占了很多。
答案 0 :(得分:1)
所以这就是我最终要做的事情,对于未来的头脑风暴:
scope :last_for_each_user, lambda {
select("orders.*") & Order.select("max(orders.id) as id").group("orders.user_id")
}
scope :first_for_each_user, lambda {
select("orders.*") & Order.select("min(orders.id) as id").group("orders.user_id")
}
如果有人有更好的想法,我非常愿意听到它。感谢整个SO社区(即使没有人回复),这是我第一次注册/提出问题,但每当我发现问题时,我都会在这里结束!
答案 1 :(得分:0)
您可以使用DISTINCT ON()
规则来获取最后一个规则。以下是模型结构的示例:
scope :for_users, lambda {|ids, is_first| includes(:user).where("user_id IN (?)", ids).select("DISTINCT ON (users.id) *").order("orders.created_at ?", is_first ? : "ASC" : "DESC") }
scope :last_for_each_users, lambda { |users| for_each_users(users.map{|u| u.id }, false }
scope :first_for_each_users, lambda { |users| for_each_users(users.map{|u| u.id }, true }