GROUP_BY内的活动记录限制

Active Record LIMIT within GROUP_BY

提问人:alenm 提问时间:2/11/2012 最后编辑:alenm 更新时间:8/18/2021 访问量:3174

问:

场景我有一个充满帖子的表格和一个用户表格。 我希望能够获取所有帖子并按用户对它们进行分组,但我想设置每个用户 10 个的限制。

class Post < ActiveRecord::Base
    belongs_to :user
end

class User < ActiveRecord::Base
    has_many :posts
end

# I thought this might work but it just grabs the first 10 posts and groups them
Post.find(:all, :limit=>10).group_by(&:user)

有什么想法吗?我是否必须为它编写自定义 SQL,或者 Active Record 可以执行此操作?

sql Ruby-on-Rails(轨道上的红宝石) 活动记录 SQLite(SQL 分组依据

评论

0赞 tadman 2/11/2012
这会将所有用户的提取次数限制为 10 次,而不是您请求的每个用户。如果它需要特定的 SQL 语句才能工作,您可能希望使用 MySQL 或您正在使用的任何 RDMBS 来标记它。
0赞 alenm 2/11/2012
好的,谢谢我在帖子中添加了 sqlite3 标签
0赞 Nick Colgan 2/11/2012
我不认为这是特定于 DB 的。ActiveRecord 可以自行处理此问题。我已经更新了我的答案以反映这一点。
0赞 alenm 2/11/2012
您的解决方案真的为每个用户获取 10 个吗?我在下面发布了一些反馈。

答:

0赞 Mattia Lipreri 2/11/2012 #1

像什么?

Post.group(:user_id).limit(10)

评论

0赞 alenm 2/11/2012
这不是我需要的,塔德曼的评论更好地说明了我想要实现的目标。我希望activerecord可以做到这一点,我可以避免编写任何自定义SQL
0赞 Nick Colgan 2/11/2012 #2
Post.group(:user_id).limit(10)

group_by不是查询方法,而是 Enumerable 的方法。

在您的代码中,在传递给 之前转换为 。上面的方法将查询方法链接在一起,并且仅在需要使用它们时将它们转换为 an。Post.find(:all, :limit => 10)Arraygroup_byArray

ActiveRecord 处理整个事情。上述方法转换为

SELECT `posts`.* FROM `posts` GROUP BY user_id LIMIT 10

评论

0赞 alenm 2/11/2012
我在 rails 控制台中尝试这个,我不明白这是如何工作的。我正在尝试返回一个哈希值,我可以迭代该哈希值以显示每个用户最多 10 个帖子。
0赞 melcher 8/18/2021 #3

我知道每个用户获取最近 10 个帖子的唯一方法需要嵌套子查询(可能存在性能问题)或 postgres 样式的横向连接。相当有信心,这不能仅通过活动记录来完成,并且需要编写自定义 SQL,您已经表明要避免这种情况。

作为无需自定义 SQL 即可完成的替代方法,您可以在时间窗口内(例如过去一个月或一年)列出每个用户及其帖子,其中包含以下内容:

class User < ActiveRecord::Base
  has_many :recent_posts, -> { where(posts: {created_at 1.month.ago..Time.now}) }, class_name: 'Post'
end

User.includes(:recent_posts).each do |user|
  user.recent_posts
end

它不会为每个用户执行 SQL 查询,因此与纯粹在 ruby 中执行查询相比,性能相对较高。