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

如何使用Django ORM实现内连接查询获取各菜系最贵菜品的完整信息

解决Django ORM查询每个菜系最高价菜品完整信息的问题

你提到的Dishes.objects.values('cuisine').annotate(max_price=Max("price"))确实只能拿到分组后的菜系和对应最高价格——因为values()会限制返回的字段,加上annotate()后是做分组聚合,没法直接拿到菜品的完整信息。下面给你两种可行的方案,其中第一种用子查询的方式更高效,符合你想要的内连接逻辑:

方案一:使用子查询(推荐)

这种方式通过子查询先计算每个菜系的最高价格,再关联原表筛选出对应价格的菜品,只需要一次数据库查询:

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

# 定义子查询:针对每个外层的菜系,计算该菜系的最高价格
max_price_subquery = Dishes.objects.filter(
    cuisine=OuterRef('cuisine')  # 引用外层查询的cuisine字段
).values('cuisine').annotate(
    max_price=Max('price')
).values('max_price')  # 只返回max_price字段作为子查询结果

# 查询符合条件的完整菜品信息
top_dishes = Dishes.objects.filter(
    price=Subquery(max_price_subquery)  # 筛选价格等于对应菜系最高价格的菜品
)

# 遍历输出示例
for dish in top_dishes:
    print(f"菜系: {dict(Dishes.cuisine_list)[dish.cuisine]}, 菜名: {dish.name}, 价格: {dish.price}, 食材: {dish.material}")

原理说明:

  • OuterRef用来引用外层查询中的cuisine字段,子查询会动态计算当前外层菜系的最高价格
  • 外层的filter(price=Subquery(...))相当于做了一次内连接,只保留价格等于对应菜系最高价格的菜品
  • 如果同一个菜系有多个菜品价格同为最高,这个查询会返回所有这些菜品;如果只需要每个菜系返回一条,可以加上.order_by('cuisine', '-price').distinct('cuisine')(注意:MySQL中使用distinct('cuisine')需要配合order_by指定该字段)

方案二:先获取最高价格集合再关联筛选

这种方式分两步,先拿到每个菜系的最高价格,再通过多条件筛选匹配原表:

from django.db.models import Max, Q

# 第一步:获取每个菜系对应的最高价格字典
cuisine_max_map = {
    item['cuisine']: item['max_price']
    for item in Dishes.objects.values('cuisine').annotate(max_price=Max('price'))
}

# 第二步:筛选出符合菜系和对应最高价格的菜品
top_dishes = Dishes.objects.filter(
    # 使用Q对象组合多个条件,确保每个菜品的菜系和价格匹配对应的最高价格
    Q(*[Q(cuisine=c, price=p) for c, p in cuisine_max_map.items()])
)

注意点:

  • 这种方式会发起两次数据库查询,数据量较大时效率不如方案一
  • 同样会返回所有价格等于菜系最高值的菜品

为什么原来的查询无法拿到完整信息?

你原来的查询使用了values('cuisine'),这会让Django ORM只返回cuisine字段和聚合后的max_price,相当于SQL中的GROUP BY cuisine,分组后只能拿到分组字段和聚合结果,无法获取分组内的其他详情字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:53:11