在我的Ruby on Rails应用程序中,我有一个像这样的数据库结构:
Project.create(:group => "1", :date => "2014-01-01")
Project.create(:group => "1", :date => "2014-01-02")
Project.create(:group => "1", :date => "2014-01-03")
Project.create(:group => "2", :date => "2014-01-01")
Project.create(:group => "2", :date => "2014-01-02")
Project.create(:group => "2", :date => "2014-01-03")
# and so forth...
如何使用ActiveRecord获取每个group
的最新记录?
解决方案可能很简单,但我无法理解这一点。
感谢您的帮助。
答案 0 :(得分:44)
在Postgres中,可以通过以下查询来实现。
SELECT DISTINCT ON ("group") * FROM projects
ORDER BY "group", date DESC, id DESC
由于此处的date
列可能不是唯一的,因此我在ORDER BY
上添加了一个额外的id DESC
条款来打破有利于具有更高ID的记录的关系,以防两个组中的记录具有相同的日期。您可能希望使用其他列,例如上次更新的日期/时间,这取决于您的用例。
继续,不幸的是ActiveRecord没有DISTINCT ON
的API,但我们仍然可以使用select
的纯SQL:
Project.select('DISTINCT ON ("group") *').order(:group, date: :desc, id: :desc)
或者如果您更喜欢使用ARel而不是使用原始SQL:
p = Project.arel_table
Project.find_by_sql(
p.project(p[Arel.star])
.distinct_on(p[:group])
.order(p[:group], p[:date].desc, p[:id].desc)
)
对于像MySQL这样的其他数据库,遗憾的是这并不方便。有多种解决方案可供选择,例如参见this answer。
答案 1 :(得分:3)
这对我有用
ids = Message.select("MAX(id) AS id").group(:column_name).collect(&:id)
@result = Message.order("created_at DESC").where(:id => ids)
答案 2 :(得分:3)
我花了一些时间对此作斗争,并认为我会分享我发现的最干净,非常简单的解决方案(假设date
或其他排序字段包含唯一值):
Project.group(:group).maximum(:date)
在qarol上发布this comment的提示。
答案 3 :(得分:0)
以下基于 this link 的解决方案适用于 MySQL,并且可以扩展到 group 表中的所有字段。
Project.select(:group, 'MAX(date) AS date').group(:group)
答案 4 :(得分:-6)
这样的东西?
Project.select(:group).map(&:group).uniq.each do |grp|
puts Project.where(group: grp).order("date DESC").last
end
这将遍历所有群组并识别唯一群组。在您的示例中,它应返回[“1”,“2”]。然后它遍历该数组并选择组ID为1的最后一个Project和组ID为2的最后一个Project。
**更新**
刚刚意识到你说“最新”而不是“最后”需要添加订单以确保最新作品。最后仍然只拉一个。
答案 5 :(得分:-10)
Project.where(:group => "1", :date => "2014-01-01").last
.last就是你要找的。 p>