Ruby on Rails:按name分组User并获取每个分组的最新用户
按Name分组获取最新User的解决方案
问题回顾
你原本想按name字段对User模型分组,拿到每个name对应的最新用户,一开始尝试的代码:
User.group(:id, :name).select(:id, :name, :created_at)
其实没达到预期——因为id是用户的唯一标识,按id+name分组相当于每个用户单独成组,根本没实现按name聚合的效果,自然筛选不出每个分组的最新用户。
你找到的可行方案(内存层面去重)
你后来尝试的这段代码已经能完美实现需求:
User.order(updated_at: :desc).uniq{ |u| u.name }
为什么这个能行?
- 先通过
order(updated_at: :desc)把所有用户按更新时间倒序排列,这样同一个name下的最新用户会排在最前面 - 再用Ruby数组的
uniq方法(带块的版本),根据name去重——因为已经排好序了,去重后留下的就是每个name对应的第一条(也就是最新的)用户记录
不过要注意:这个方法会先把所有用户数据加载到内存里再去重,如果你的用户表数据量很大,可能会有内存占用过高的问题。
进阶优化:数据库层面筛选(适合大数据量)
如果要处理大量数据,更推荐直接在数据库层面用窗口函数完成分组筛选,以PostgreSQL为例:
User.from( User.select( '*', 'ROW_NUMBER() OVER (PARTITION BY name ORDER BY updated_at DESC) as rn' ), :users ).where(rn: 1)
这个思路是给每个name分组内的用户按updated_at倒序编号,然后只取编号为1的记录(也就是每个分组的最新用户),全程在数据库操作,性能会好很多。
内容的提问来源于stack exchange,提问作者Lucas Andrade
相关产品推荐
相关产品推荐

