Django聚合仅计数True值

时间:2014-08-11 19:00:54

标签: python django aggregate

我使用聚合来计算一列布尔值。我想要真值的数量。

DJANGO CODE:

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

这将返回所有行的计数。

SQL QUERY应该是:

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'),
)

3 个答案:

答案 0 :(得分:23)

更新了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))))

更多信息:

答案 1 :(得分:3)

更新

从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)),
            default = Value(0)
        )
    )
)

了解Conditional Expression classes

旧答案。

您希望做的是某种“条件聚合”。目前Aggregation个函数不支持filterexclude等查找:fieldname__lt,fieldname__gt,...

所以你可以试试这个:

django-aggregate-if

摘自官方网页。

  

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

您还可以首先annotate每个团队所需的值,我的意思是每个团队在您感兴趣的字段中计算True的数量。然后执行您想要做的所有aggregation

答案 2 :(得分:1)

伯尔伯爵的另一个解决方案是:

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,然后仅转换Sum