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

Rails中按item_id分组、按score排序取每组前3并返回关联Book的实现问题

Rails 分组取Top N关联数据实现方案

首先要先在模型中声明好关联关系:

# app/models/item_statistic.rb
class ItemStatistic < ApplicationRecord
  belongs_to :book
end

# app/models/book.rb
class Book < ApplicationRecord
  has_many :item_statistics
end

方案1:SQL窗口函数实现(推荐,大数据量性能优)

适配PostgreSQL、MySQL 8.0+等支持窗口函数的数据库,直接在数据库层完成筛选逻辑,避免全量加载数据:

# 先按item_id分组、按score倒序排序,每组取前3条记录
top_statistics = ItemStatistic.select(
  "*, ROW_NUMBER() OVER (PARTITION BY item_id ORDER BY score DESC) AS rank_num"
).where("rank_num <= 3")

# 预加载关联Book避免N+1查询,构造目标格式哈希
result = top_statistics.preload(:book).each_with_object({}) do |stat, hash|
  item_id = stat.item_id
  hash[item_id] ||= []
  hash[item_id] << stat.book.attributes.symbolize_keys
end

如果需要按score升序排序,删除ORDER BY score DESC中的DESC即可

方案2:Ruby层处理(适合小数据量,写法更简洁)

数据量不大的场景可以直接在Ruby层做分组筛选,不需要写原生SQL:

result = ItemStatistic.preload(:book)
                      .order(score: :desc)
                      .group_by(&:item_id)
                      .transform_values do |stats|
                        stats.take(3).map { |stat| stat.book.attributes.symbolize_keys }
                      end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 18:36:04