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

如何在Django中不使用values()实现GROUP BY并返回模型实例QuerySet

Django ORM 分组查询返回模型实例QuerySet实现方案

首先明确SQL基础逻辑:标准GROUP BY语法会将指定字段值相同的多行合并为单条聚合结果,单条聚合结果无法直接映射分组内包含的所有原始模型记录,以下方案根据不同业务场景返回带聚合注解的模型实例QuerySet,替代values()返回的字典结果集。


方案1:从关联主表侧发起查询(推荐,适用于分组字段为外键的场景)

如果你的category字段是关联Category模型的外键字段,直接从关联的主模型侧查询,天然返回模型实例,不需要调用values()。
假设模型定义如下:

class Category(models.Model):
    name = models.CharField(max_length=100)

class Participant(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="participants")
    price = models.DecimalField(max_digits=10, decimal_places=2)

查询代码:

from django.db.models import Avg, F

# 返回Category模型的常规QuerySet,每个实例自带分组聚合的average属性
category_qs = Category.objects.annotate(
    average=Avg(F("participants__price"))
)

# 直接读取实例属性即可
for cat in category_qs:
    print(cat.name, cat.average)

这个方案是Django ORM最推荐的分组写法,完全符合ORM关联查询设计,无额外性能损耗。


方案2:使用窗口函数(适用于需要返回所有原始模型实例、同时携带分组聚合值的场景)

如果你需要返回所有Participant模型实例,且每个实例上附带其所属category分组的平均价格,可以用窗口函数替代GROUP BY,不需要合并行,返回结果全是Participant模型实例:

from django.db.models import Avg, F, Window

participant_qs = Participant.objects.annotate(
    average=Window(
        expression=Avg(F("price")),
        partition_by=F("category") # 按category分区,对应分组维度
    )
)

注意:窗口函数不会做行合并,同一个category下的所有Participant记录都会被返回,同组记录的average属性值完全相同。


方案3:子查询+去重(适用于分组字段为普通字段、单分组返回单条模型实例的场景)

如果category是存字符串的普通字段(不是外键),且需要和原values()分组逻辑保持一致(每个category只返回一条结果),可以通过子查询给实例注解聚合值后按分组字段去重:

from django.db.models import Avg, F, OuterRef, Subquery

# 构建分组聚合的子查询
avg_sub = Participant.objects.filter(
    category=OuterRef("category")
).annotate(avg=Avg("price")).values("avg")[:1]

# 给原始实例注解聚合值,按category去重,每个分组取第一条实例
participant_qs = Participant.objects.annotate(
    average=Subquery(avg_sub)
).distinct("category")

注意:带字段参数的distinct()方法仅支持PostgreSQL数据库,如果使用MySQL等其他数据库,可以在业务层做二次遍历去重;如果需要指定每个分组返回的实例规则,可以在distinct()前加order_by('category', '-price')这类排序规则,自定义分组内返回的实例。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:45:49