Django聚合仅计数True值

16 投票
4 回答
13488 浏览
提问于 2025-04-18 16:52

我正在使用聚合函数来计算一个布尔值列的数量。我想知道有多少个值是True。

这是我的DJANGO代码:

count = Model.objects.filter(id=pk).aggregate(bool_col=Count('my_bool_col')

这段代码返回的是所有行的数量。

正确的SQL查询应该是:

SELECT count(CASE WHEN my_bool_col THEN 1 ELSE null END) FROM <table_name>

这是我实际的代码:

stats = Team.objects.filter(id=team.id).aggregate(
    goals=Sum('statistics__goals'),
    assists=Sum('statistics__assists'),
    min_penalty=Sum('statistics__minutes_of_penalty'),
    balance=Sum('statistics__balance'),
    gwg=Count('statistics__gwg'),
    gk_goals_avg=Sum('statistics__gk_goals_avg'),
    gk_shutout=Count('statistics__gk_shutout'),
    points=Sum('statistics__points'),
)

感谢Peter DeGlopper的建议,使用了django-aggregate-if

这是解决方案:

from django.db.models import Sum
from django.db.models import Q
from aggregate_if import Count

stats = Team.objects.filter(id=team.id).aggregate(
    goals=Sum('statistics__goals'),
    assists=Sum('statistics__assists'),
    balance=Sum('statistics__balance'),
    min_penalty=Sum('statistics__minutes_of_penalty'),
    gwg=Count('statistics__gwg', only=Q(statistics__gwg=True)),
    gk_goals_avg=Sum('statistics__gk_goals_avg'),
    gk_shutout=Count('statistics__gk_shutout', only=Q(statistics__gk_shutout=True)),
    points=Sum('statistics__points'),
)

4 个回答

0

这个对我有效:

from django.db.models import Avg, Sum, Count, Q 

aggregated_values = queryset.aggregate(
        avg_length=Avg('field_name'),
        total_reserved=Count('field_name', filter=Q(field_name=True)),
        total_not_reserved=Count('field_name', filter=Q(field_name=False))
    )
6

另一种计算布尔值的方法是:

from django.db.models import Sum, IntegerField
from django.db.models.functions import Cast

Model.objects.filter(id=pk).annotate(bool_col=Sum(Cast('my_bool_col', IntegerField())))

只需把 False 转换为 0,把 True 转换为 1,然后再把这些数字加起来就可以了。

32

这是针对Django 1.10的更新。现在你可以进行条件聚合了:

from django.db.models import Count, Case, When
query_set.aggregate(bool_col=Count(Case(When(my_bool_col=True, then=1))))

更多信息请查看:

9

更新:

自从Django 1.10版本开始,你可以:

from django.db.models import Count, Case, When
query_set.aggregate(
    bool_col=Count(
        Case(When(my_bool_col=True, then=Value(1)))
    )
)

可以了解一下条件表达式类

旧答案。

看起来你想做的事情是一种“条件聚合”。目前,聚合函数不支持像filterexclude这样的查找方式,比如字段名小于(__lt)、字段名大于(__gt)等。

所以你可以试试这个:

django-aggregate-if

以下是官网的描述:

为Django查询提供条件聚合,就像Excel中的著名SumIf和CountIf一样。

你也可以先注释每个团队所需的值,也就是统计每个团队在你感兴趣的字段中有多少个True。然后再进行你想要的所有聚合操作。

撰写回答