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

如何优化ActiveRecord查询以获取MySQL中loco_no列的唯一最新记录

优化ActiveRecord查询获取每个loco_no的最新记录

要实现每个loco_no只返回最新(按updated_at降序)的is_live: true记录,这里有几种可靠的方案,根据你使用的数据库选择最适合的:

方案一:PostgreSQL专属(简洁高效)

PostgreSQL支持DISTINCT ON语法,能直接按指定字段分组并取每组的第一条记录:

LocoUpdate.where(is_live: true)
          .order(:loco_no, updated_at: :desc) # 先按loco_no分组,组内按updated_at倒序
          .distinct_on(:loco_no) # 保留每个loco_no的第一条记录

这个查询会先把所有符合条件的记录按loco_no分组,每组内按updated_at从新到旧排序,然后只保留每组的第一条,完美匹配你的需求。

方案二:跨数据库兼容(用窗口函数)

如果你的项目需要兼容MySQL、SQLite等其他数据库,窗口函数ROW_NUMBER()是更通用的选择:

# 子查询:给每个loco_no分组的记录添加行号,最新的记录行号为1
subquery = LocoUpdate.where(is_live: true)
                     .select(
                       "loco_updates.*",
                       "ROW_NUMBER() OVER (PARTITION BY loco_no ORDER BY updated_at DESC) AS rn"
                     )

# 外层查询:筛选出行号为1的记录
LocoUpdate.from("(#{subquery.to_sql}) AS loco_updates")
          .where(rn: 1)

原理是通过窗口函数给每个loco_no下的记录按updated_at倒序分配行号,然后只保留行号为1的那条,也就是每个分组的最新记录。

方案三:基于ID的分组(需谨慎使用)

如果你的LocoUpdate表中,updated_at最晚的记录对应的id也最大(比如默认的自增ID),可以用更简单的分组查询:

# 先获取每个loco_no对应的最新记录ID
latest_ids = LocoUpdate.where(is_live: true)
                       .group(:loco_no)
                       .select("MAX(id) AS id")

# 通过ID查询完整记录
LocoUpdate.where(id: latest_ids)

⚠️ 注意:这个方法仅当id的增长和updated_at的更新完全同步时才可靠,如果存在同一时间多条记录或者ID不按时间递增的情况,可能会返回错误的结果。

以上几种方法都能帮你得到期望的结果:每个loco_no仅保留最新的那条is_live: true的记录,和你给出的示例结果一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 11:23:37