如何在Django ORM中聚合多个已聚合值的总和(Django 3.2.10 + PostgreSQL 13.4)
在Django 3.2中实现聚合结果的求和(trues + falses = total)
嘿,这个问题我之前也碰到过——Django的aggregate方法里确实没法直接像你写的那样引用前面定义的trues和falses别名,不过有两种实用的解决办法,根据你的场景选就行:
方法一:直接计算总记录数(最简洁高效)
如果你的criteria字段是非空布尔类型(没有Null值),那trues + falses其实就是整个QuerySet的总记录数,直接用Count('id')就能得到total,而且数据库只需要扫描一次表,效率更高:
from django.db.models import Count, Q queryset = Model.objects.all().aggregate( trues=Count('id', filter=Q(criteria=True)), falses=Count('id', filter=Q(criteria=False)), total=Count('id') )
方法二:在数据库层面聚合求和(适用于复杂场景)
如果criteria可能存在Null值,或者你需要基于其他聚合结果求和(不只是简单的Count),可以用ExpressionWrapper结合F表达式,让数据库直接把trues和falses的结果相加:
from django.db.models import Count, Q, F, ExpressionWrapper, IntegerField queryset = Model.objects.all().aggregate( trues=Count('id', filter=Q(criteria=True)), falses=Count('id', filter=Q(criteria=False)), total=ExpressionWrapper(F('trues') + F('falses'), output_field=IntegerField()) )
这里的F表达式用来引用聚合中已定义的别名,ExpressionWrapper则指定输出字段类型为整数,确保结果正确。
内容的提问来源于stack exchange,提问作者Vadim Beglov




