父母和孩子的created_at订购的最佳方式是什么?

时间:2014-01-11 10:03:00

标签: ruby-on-rails postgresql activerecord

假设我的父评论有很多回复。

class Comment < ActiveRecord::Base
    has_many :replies

class Reply < ActiveRecord::Base
    belongs_to :topic

我想按created_at订购我的评论,如果他们有更新的回复,我希望家长评论按其最新回复{{1}排序而不是它自己的created_at。

因此,例如,如果我有3条评论,一条为第1天,第2天和第3天发布。第1天是最早的,但第2天有今天发布的回复,我该如何对其进行排序以便结果将是:

created_at

第2天的是最近的活动,比当天早些时候发布的第3天评论更新。

这会是什么方法?

4 个答案:

答案 0 :(得分:2)

最好通过您的模型处理日期:

class Comment < ActiveRecord::Base
  has_many :replies
end

class Reply < ActiveRecord::Base
  belongs_to :comment, touch: true
end

请注意touch: true关联中的belongs_to: comment。保存updated_at

时,这会更新父Comment的{​​{1}}属性

现在只需在选择评论时按Reply排序。

答案 1 :(得分:2)

最佳查询(如最佳效果)是添加额外的last_activity列。保持后者(自动,使用触发器或一些RoR内置糖)并在其上添加索引。然后,您将能够使用普通查询获取该列排序的行。

备选方案是与聚合的丑陋连接(请参阅一小时前的答案)。它不会很漂亮,随着你的桌子大小的增长,它会执行非常

答案 2 :(得分:1)

我想这样的事情可能“好”,但请查看查询计划。 (我自己只处理LINQ和SQL Server - YMMV。)

select * from comments c 
left join (select r.comment_id, max(r.created_at) as created_at
           from replies r
           group by r.comment_id) lr
on lr.comment_id = c.comment_id
order by isnull(lr.created_at, c.created_at) desc

答案 3 :(得分:1)

LEFT JOIN到最新响应(可能不存在,因此为LEFT)后,在ORDER BY中使用(SQL标准)COALESCE。但根据您的要求,只有来自SELECT的{​​{1}}列:

comments

由于逻辑规定回复必须在评论之后。如果不是这样,那么您可以使用SELECT c.* FROM comments c LEFT JOIN ( SELECT comment_id, max(created_at) AS created_at FROM replies GROUP BY 1 ) r USING (comment_id) ORDER BY COALESCE(r.created_at, c.created_at) DESC