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

如何用Rails查询按parent_id分组并获取每组最大version的行?

Rails 查询:按parent_id分组并获取每组version最大的行

给定表结构:

| id | parent_id | version | other columns ... |
| 1  | 10        | 1       | ...               |
| 2  | 10        | 2       | ...               |
| 3  | 23        | 1       | ...               |
| 4  | 55        | 1       | ...               |
| 5  | 55        | 2       | ...               |
| 6  | 55        | 3       | ...               |

需要实现:

  • 按parent_id字段分组
  • 定位每组中version值最大的行(无重复版本值)
  • 优先返回ActiveRecord对象集合,至少能拿到目标行的id数组

期望结果为id=2、3、6的行。

实现方案

方法1:子查询关联(兼容大多数数据库)

先通过分组查询拿到每个parent_id对应的最大版本号,再关联原表筛选出符合条件的记录:

# 替换YourModel为你的实际模型类名
max_version_subquery = YourModel.group(:parent_id).select(:parent_id, 'MAX(version) AS max_version')

# 关联子查询,获取目标记录
target_records = YourModel.joins(
  "JOIN (#{max_version_subquery.to_sql}) AS max_v ON your_models.parent_id = max_v.parent_id AND your_models.version = max_v.max_version"
)

# 若只需要id数组
target_ids = target_records.pluck(:id) # => [2, 3, 6]

注:如果你的模型对应的表名不是your_models,需要替换为实际表名。

方法2:窗口函数(Rails 5+,数据库需支持窗口函数如PostgreSQL/MySQL 8+)

用窗口函数按parent_id分区,按version倒序排序后取每组的第一行:

# 替换YourModel为你的实际模型类名
target_records = YourModel.select('your_models.*').from(
  YourModel.select('your_models.*', 'ROW_NUMBER() OVER (PARTITION BY parent_id ORDER BY version DESC) AS rn')
).where(rn: 1)

# 获取id数组
target_ids = target_records.pluck(:id) # => [2, 3, 6]

这种写法更简洁,且能直接返回完整的ActiveRecord对象,适合需要操作模型实例的场景。

补充说明

很多人一开始会尝试直接用group后取整行,但group本质是聚合操作,只能返回分组字段和聚合函数结果,无法直接拿到整行数据,所以需要通过子查询或窗口函数间接实现,这也是这类需求看似简单但容易卡壳的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:57:20