什么是Rails 3的订购方式.group()结果是Activerecord(这里是“created_at”)?
@messages = Message.group(:foo)
仅导致显示最早的消息。我需要最新的展示。
我试过
@messages = Message.group(:foo).having("created_at = MAX(created_at)")
没有成功。任何提示赞赏!
澄清:我希望在自己内部订购该组,而不是正常的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")
但是这只检索单个记录(未分组的记录)。据推测,分组的那些被省略。不知道为什么,所有记录都有:created_at和:foo值
答案 0 :(得分:6)
您不能在某些数据库下的同一查询中使用order then group,因此您需要使用两个查询来执行此操作:
message_ids = Message.select("MAX(id) AS id").group(:foo).collect(&:id)
@messages = Message.order("created_at DESC").where(:id => message_ids)
注意:这假设您有一个自动递增的id
列,大多数Rails表都会这样做。
答案 1 :(得分:2)
您可以使用SQL,但您也可以使用
保持在activerecord土地上@messages = Message.select('DISTINCT ON (foo) *').order(:created_at).reverse_order
DISTINCT ON ()
语法是postgres。在MYSQL中有类似但略有不同的语法。
我认为这个查询最终会比接受的答案更有效率,因为它只是一种排序和扫描,而不是N种类。
答案 2 :(得分: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
感谢Chaos在这个帖子中的回答:Select the 3 most recent records where the values of one column are distinct
但是,不知道任何速度影响。如果有人想介入,请随意这样做。
答案 3 :(得分:1)
我刚遇到同样的问题。以下Rails查询对我有用:
Message.where("id IN (SELECT MAX(id) FROM messages GROUP BY id) AND state = 'unread'")
在这里,我们使用子查询来获取每个组中最大的(因此也是最近的)ID,然后将这些ID过滤为仅显示state ==' unread'。
的那些ID。提示:我在Message模型类中创建了一个self.latest方法,该方法包含:
def self.latest
where("id IN (SELECT MAX(id) FROM messages GROUP BY id)
end
这意味着我可以在这样的控制器中使用它:
Message.latest.where(state: 'unread')
答案 4 :(得分:0)
我没有看到如何使用Arel轻松完成这项工作 - 但如果您只是像在问题中那样构建自己的SQL,那么请按如下方式修改它:
@messages = Message.find_by_sql("
SELECT messages.*
FROM messages
GROUP BY messages.foo
HAVING messages.created_at = (SELECT max(created_at) FROM messages AS sub_messages WHERE sub_messages.foo = messages.foo)
请注意HAVING子句中的子查询。您的HAVING子句计算了所有消息中的MAX - 而不是foo中的消息。子查询应该解决这个问题。
我将消息表名称别名为sub_messages - 但这不是必需的。我只是为了“显示”父和子查询如何协同工作。