Rails 3:.group()由created_at排序

Dav*_*vid 13 activerecord group-by sql-order-by ruby-on-rails-3

什么是Rails 3的订购方式.group()结果是Activerecord(这里是"created_at")?

@messages = Message.group(:foo)
Run Code Online (Sandbox Code Playgroud)

只会导致显示最早的消息.我需要最新的展示.

我试过了

@messages = Message.group(:foo).having("created_at = MAX(created_at)")
Run Code Online (Sandbox Code Playgroud)

没有成功.任何提示赞赏!

澄清一下:我希望在自己内部订购该组,而不是正常的messages.order("...").如果没有简单的Activerecord语法,我也会对原始SQL感到满意


更新:尝试SQL方式,这应该工作:

@messages = Message.find_by_sql("
  SELECT messages.* 
  FROM messages 
  GROUP BY messages.foo 
  HAVING messages.created_at = MAX(messages.created_at) 
  ORDER BY messages.created_at DESC")
Run Code Online (Sandbox Code Playgroud)

但是这只检索单个记录(未分组的记录).据推测,分组的那些被省略.不知道为什么,所有记录都有:created_at和:foo值

Mik*_*ike 6

您不能在某些数据库下的同一查询中使用order然后分组,因此您需要使用两个查询来执行此操作:

message_ids = Message.select("MAX(id) AS id").group(:foo).collect(&:id)
@messages = Message.order("created_at DESC").where(:id => message_ids)
Run Code Online (Sandbox Code Playgroud)

注意:这假设您有一个自动递增的id列,大多数Rails表都会这样做.


Dav*_*vid 1

通过使用更专用的子查询,无需 GROUP BY 调用,一切都可以正常工作:

SELECT *
   FROM `messages`
   WHERE `id` = (
      SELECT `id`
      FROM `messages` as `alt`
      WHERE `alt`.`foo` = `messages`.`foo`
      ORDER BY `created_at` DESC
      LIMIT 1
   )
   ORDER BY `created_at` DESC
Run Code Online (Sandbox Code Playgroud)

这一切都归功于 Chaos 在这个线程中的回答:选择其中一列的值不同的 3 个最新记录

但还不知道对速度有什么影响。如果有人想介入,请随意这样做。