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

如何用Django ORM的annotate与Subquery获取各店铺最低价商品

用Django的annotate和Subquery实现每个店铺筛选后商品的最低成本商品查询

没问题,我来帮你搞定这个需求!要实现从每个店铺的筛选后商品集合里,拿到total_cost最低的那件商品,结合annotate和Subquery可以分两步来实现,逻辑清晰且性能友好。

步骤1:定义你的基础筛选商品集合

首先先确认你已经有了筛选后的商品集合,比如假设你是按某个分类、时间范围筛选的,先把这个集合定义好:

from django.db.models import Subquery, OuterRef, Min

# 这里替换成你的实际筛选条件,比如按商品类型、上架时间等
filtered_goods = Goods.objects.filter(
    # 示例条件:比如商品属于某个分类
    # category='daily_necessities'
)

步骤2:构建子查询获取每个店铺的最低成本值

先通过子查询计算出每个店铺在筛选后的商品中,total_cost的最小值:

# 子查询:针对每个店铺,计算其筛选后商品的最小total_cost
min_cost_subquery = filtered_goods.filter(
    store=OuterRef('pk')  # 关联外层查询的Store主键
).values('store').annotate(
    min_cost=Min('total_cost')
).values('min_cost')

步骤3:匹配到对应最低成本的商品

接下来再构建一个子查询,找到每个店铺中total_cost等于上述最小值的商品(如果有多个相同最小值的商品,我们用[:1]确保每个店铺只返回一条,你可以根据需求调整排序规则):

# 子查询:获取每个店铺中符合筛选条件且成本最低的商品ID
lowest_cost_good_subquery = filtered_goods.filter(
    store=OuterRef('pk'),
    total_cost=Subquery(min_cost_subquery)
).order_by('id')[:1]  # 按id排序取第一个,避免多条重复最小值的情况

步骤4:获取最终结果

最后通过商品ID筛选,得到每个店铺对应的最低成本商品集合:

# 最终查询结果:每个店铺筛选后商品中成本最低的那件
result = Goods.objects.filter(
    pk__in=Subquery(lowest_cost_good_subquery)
)

额外技巧:直接从Store模型关联查询

如果你需要同时获取店铺信息和对应的最低成本商品,可以直接在Store查询中annotate:

stores_with_lowest_good = Store.objects.annotate(
    lowest_good_id=Subquery(lowest_cost_good_subquery)
).filter(lowest_good_id__isnull=False)

# 若要直接拿到Goods对象,可通过id筛选
goods_result = Goods.objects.filter(
    pk__in=stores_with_lowest_good.values('lowest_good_id')
)

注意事项

  • 如果你的筛选条件比较复杂,确保filtered_goods已经正确包含了所有需要考虑的商品。
  • 当多个商品的total_cost完全相同时,order_by('id')[:1]会取id最小的那条,你可以改成order_by('-create_time')[:1]来取最新上架的,根据业务需求调整即可。
  • OuterRef的作用是引用外层查询的字段,这里外层如果是Store查询就用OuterRef('pk'),如果是Goods查询要对应调整引用的字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:28:47