You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于指定列筛选ActiveRecord的前n条唯一记录?

解决ActiveRecord按指定列去重并获取前n条完整对象的问题

我懂你的需求啦——你想基于特定列(比如name)去重,只保留每个唯一值对应的第一条记录,然后取前n条完整的Recommendation对象,而不是只拿到字段值对吧?之前用limit或者单纯的distinct确实达不到效果,因为前者不管重复直接取前n条,后者搭配pluck只能拿字段,没法返回完整模型实例。

这里给你两个靠谱的解决方案,适配不同场景:

方案一:通用窗口函数法(支持所有主流数据库)

利用窗口函数实现精准分组去重,同时保留完整对象:

# 第一步:构建子查询,给每个name分组的记录标记行号
ranked_recommendations = Recommendation.select(
  "recommendations.*",
  # 按name分组,组内按id升序排序,给每条记录标记行号
  "ROW_NUMBER() OVER (PARTITION BY name ORDER BY id ASC) AS row_num"
).where(id: [1,2,3,4]) # 你的初始筛选条件

# 第二步:从子查询中筛选每个分组的第一条记录,再取前2条
unique_top_recommendations = Recommendation.from(ranked_recommendations, :recommendations)
                                           .where(row_num: 1)
                                           .limit(2)

原理说明

ROW_NUMBER() OVER (PARTITION BY name ORDER BY id ASC) 会把相同name的记录归为一组,每组内按id从小到大排序,给第一条记录标记row_num=1,后续同name的记录行号递增。我们只筛选row_num=1的记录,就得到了每个唯一name对应的第一条记录,再用limit(2)就能拿到你要的结果(比如记录1和记录3,而非重复的记录1和2)。

方案二:PostgreSQL专属简化法(Rails 7+)

如果你用的是PostgreSQL数据库,且Rails版本在7及以上,可以用distinct_on语法简化写法:

Recommendation.where(id: [1,2,3,4])
              .distinct_on(:name)
              .order(:name, :id)
              .limit(2)

这个方法会按name去重,自动保留每个name组内按id排序的第一条记录,同样能返回完整的模型实例,语法更简洁,但仅适用于PostgreSQL环境。

内容的提问来源于stack exchange,提问作者user2954587

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:28:58