如何用Django ORM获取各产品对应的最高单价记录
解决方案
问题分析
你之前的代码使用aggregate(Max("unit_price"))会计算筛选后整个查询集的全局最高单价,而非按每个产品分组计算。要实现每个产品对应最高单价的OrderLine记录,需要先按product_id分组获取每组的最大值,再关联到具体记录。
方法一:分组取最高单价后关联查询
先查询每个产品对应的最高单价,再匹配对应的记录:
from django.db.models import Max # 按product_id分组,获取每个产品的最高单价 product_max_prices = OrderLine.objects.filter( transfer_id__in=to_ids, product_id__in=part_ids ).values("product_id").annotate(max_price=Max("unit_price")) # 提取(product_id, max_price)的元组列表 price_pairs = [(item["product_id"], item["max_price"]) for item in product_max_prices] # 获取每个产品对应最高单价的OrderLine记录 to_lines = OrderLine.objects.filter( transfer_id__in=to_ids, product_id__in=part_ids, # 匹配每个产品的id和对应最高单价 models.Q(*[models.Q(product_id=p, unit_price=pr) for p, pr in price_pairs]) ).distinct()
注:如果同一产品有多个记录单价同为最高值,distinct()会去重;若需保留所有同价记录,移除distinct()即可。
方法二:Subquery高效筛选
用Django的Subquery和OuterRef直接在查询中筛选,减少数据库查询次数:
from django.db.models import Subquery, OuterRef, Max # 子查询:获取当前外层查询产品的最高单价 max_price_subquery = OrderLine.objects.filter( product_id=OuterRef("product_id"), transfer_id__in=to_ids ).values("product_id").annotate(max_price=Max("unit_price")).values("max_price") # 主查询:筛选出单价等于对应产品最高单价的记录 to_lines = OrderLine.objects.filter( transfer_id__in=to_ids, product_id__in=part_ids, unit_price=Subquery(max_price_subquery) ).distinct()
该方法仅需两次数据库查询,数据量较大时性能更优。
原代码失效原因
values("unit_price")仅返回单价字段,丢失了按product_id分组的关键信息aggregate()是全局聚合函数,只会返回整个查询集的单一最大值,不支持分组聚合结果
内容的提问来源于stack exchange,提问作者Hemal Patel
相关产品推荐
相关产品推荐

