GROUP_BY 内的活动记录 LIMIT

Posted

技术标签:

【中文标题】GROUP_BY 内的活动记录 LIMIT【英文标题】:Active Record LIMIT within GROUP_BY 【发布时间】:2012-03-03 09:38:33 【问题描述】:

场景 我有一张满是帖子的桌子,里面有一张用户表。 我希望能够获取所有帖子并按用户分组,但我希望将限制设置为每个用户 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 可以这样做?

【问题讨论】:

这将所有用户的获取限制为 10,而不是您请求的 per-user。如果它需要特定的 SQL 语句才能工作,您可能希望使用 mysql 或您正在使用的任何 RDMBS 对其进行标记。 好的,谢谢我在帖子中添加了 sqlite3 标签 我不认为这是特定于数据库的。 ActiveRecord 可以自行处理。我已经更新了我的答案以反映这一点。 您的解决方案真的可以为每个用户获取 10 个吗?我在下面发布了一些反馈。 【参考方案1】:

类似的东西?

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

【讨论】:

这不是我需要的 tadman 的评论更好地说明了我想要实现的目标。我希望 activerecord 可以做到这一点,我可以避免编写任何自定义 SQL【参考方案2】:
Post.group(:user_id).limit(10)

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

在您的代码中,Post.find(:all, :limit =&gt; 10) 在被传递给group_by 之前被转换为Array。上述方法将查询方法链接在一起,只有在需要时才将它们转换为Array

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

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

【讨论】:

我在 Rails 控制台中尝试这个,但我不知道它是如何工作的。我正在尝试返回一个哈希值,我可以对其进行迭代以显示每个用户最多 10 个帖子。【参考方案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​​ 中执行相比性能相对较高。

【讨论】:

以上是关于GROUP_BY 内的活动记录 LIMIT的主要内容,如果未能解决你的问题,请参考以下文章

在 sqlalchemy 中使用 distinct()/group_by() 获取基于每个“名称”列的最新记录

使用 group_by 将第一个创建记录的标识符添加到 select 语句

Codeigniter 中由 distinct() 或 group_by() 过滤的计数结果

R语言dplyr包使用group_by函数arrange函数和filter函数获取每个分组的第一个第N个最后一个记录实战

Python计算素数学习记录

django的group_by