Rails多表查询:如何按供应商ID分组仅返回单条最新记录?
解决供应商最新价格记录重复问题
问题核心
你当前的查询会拉取所有符合item_id=1且item_code不为空的价格记录,所以同一供应商有多条价格记录时就会重复出现。直接用group(:id)报错是因为SQL的分组规则:SELECT的字段要么是分组字段,要么是聚合函数,强行把item_code加入分组又会把同一供应商不同item_code的记录分开,达不到去重效果。
解决方案
方案1:子查询筛选最新价格记录ID
先找出每个供应商对应目标商品的最新价格记录ID,再关联供应商查询:
# 第一步:获取每个供应商对应item_id=1的最新价格记录ID latest_price_ids = Price.where(item_id: 1) .where.not(item_code: nil) .group(:supplier_id) .maximum(:created_at) .flat_map do |supplier_id, max_created_at| Price.where( supplier_id: supplier_id, created_at: max_created_at, item_id: 1 ).pluck(:id) end # 第二步:关联供应商,获取去重后的结果 Supplier.joins(:prices) .where(prices: { id: latest_price_ids }) .pluck(:id, :item_code)
这个思路先通过group(:supplier_id)拿到每个供应商的最新价格创建时间,再匹配对应的价格记录ID,最后关联供应商,确保每个供应商只返回一条最新记录。
方案2:用窗口函数(适合PostgreSQL/MySQL 8+等支持窗口函数的数据库)
窗口函数可以直接给每个供应商的价格记录按创建时间排序,取第一条:
Supplier.joins(<<-SQL) INNER JOIN ( SELECT *, ROW_NUMBER() OVER (PARTITION BY supplier_id ORDER BY created_at DESC) AS row_num FROM prices WHERE item_id = 1 AND item_code IS NOT NULL ) latest_prices ON suppliers.id = latest_prices.supplier_id AND latest_prices.row_num = 1 SQL .pluck(:id, :latest_prices_item_code)
这里用ROW_NUMBER()按供应商分组,每组内按created_at降序编号,取row_num=1的就是每个供应商的最新价格记录,关联后自然不会有重复。
内容的提问来源于stack exchange,提问作者yeahNah
相关产品推荐
相关产品推荐

