按计数排序多个关联

时间:2014-07-31 22:47:30

标签: sql ruby-on-rails ruby postgresql

我有一个帖子模型。帖子has_many评论,has_many收藏,并且帖子模型上有一个名为views的列。我想通过所有这3个计数的总和来订购帖子。如何用示波器实现这一目标?

4 个答案:

答案 0 :(得分:1)

您可以使用find_by_sql编写您想要的任何sql。

示例代码:

Post.find_by_sql("select posts.id,posts.title, 
  count(distinct comments.id) as comments_cnt,
  count(distinct favorites.id) as favorites_cnt 
  from posts
  left join comments on  comments.post_id = posts.id
  left join favorites on favorites.post_id = posts.id
  group by posts.id,posts.title
  order by max(posts.views) +  comments_cnt + favorites_cnt DESC")

编辑:

上面的代码仅适用于sql_lite或db2,适用于其他dbms:

Post.find_by_sql("select posts.id,posts.title, 
  count(distinct comments.id) as comments_cnt,
  count(distinct favorites.id) as favorites_cnt 
  from posts
  left join comments on  comments.post_id = posts.id
  left join favorites on favorites.post_id = posts.id
  group by posts.id,posts.title
  order by max(posts.views) +  count(distinct comments.id) + count(distinct favorites.id) DESC")

答案 1 :(得分:1)

你可以制作类似的东西:

scope :by_views_comments_and_favorites_count, lambda do |order|
  joins(:comments, :favorites)
  .select("
    count(distinct comments.id) comments_count, 
    count(distinct favorites.id) favs_count, 
    views"
  )
  .group('posts.id')
  .order("(favs_count + comments_count + views) #{order}")
end

并使用这样的范围:

Post.by_views_comments_and_favorites_count('desc')

如果您想要包含可能没有评论或收藏的帖子子集,那么您可以将这两个表的INNER JOIN更改为LEFT JOIN,例如

joins('left join comments on comments.post_id = posts.id')
.joins('left join favorites on favorites.post_id = posts.id')

答案 2 :(得分:0)

如果您想有效地执行此操作(例如,如果您预计会有成千上万的帖子,有数万条评论和收藏),那么您应该在帖子模型/表格中创建一个“得分”列。当您注册视图,评论或收藏时更新您的分数(views + comments.count + favourites.count)。然后,您可以在所选数据库的分数列上创建索引,按该列排序将非常简单,超级快速。

答案 3 :(得分:-1)

我不能给你一个Ruby答案,但这是一个SQL答案:

WITH post_counts as (
SELECT post.post_id, post.views,
   COUNT (DISTINCT comment.post_id) as count_comments,
   COUNT (DISTINCT favorite.post_id) as count_favorites
FROM post
   LEFT JOIN comment ON post.id = comment.post_id
   LEFT JOIN favorite ON post.id = favorite.post_id
)
SELECT post_id, views, count_comments, count_favorites
FROM post_counts
ORDER BY views + count_comments + count_favorites DESC;

我不知道如何将其转换为Rails视图。