我正在尝试执行django聚合函数,但无法产生所需的结果。
我得到了什么:
income_posts.values_list('category__name','amount')
[(u'Donation', Decimal("2000.00")), (u'Paycheck', Decimal("1200.00")), (u'Donation', Decimal("1000.00"))]
期望的结果:
[(u'Donation', Decimal("3000.00")), (u'Paycheck', Decimal("1200.00))]
我需要汇总具有相同category__name的'amount'字段。
答案 0 :(得分:17)
来自this answer for a related question:
from django.db.models import Sum
income_posts.values('category__name').order_by('category__name').annotate(total=Sum('amount'))
答案 1 :(得分:4)
只需添加到arjun27的答案中即可。由于该软件包似乎已被放弃,您可能只想复制其中需要的3行:
from django.db.models import Sum
class DistinctSum(Sum):
function = "SUM"
template = "%(function)s(DISTINCT %(expressions)s)"
可以与上面相同地使用:
income_posts.annotate(total=DistinctSum('amount')
答案 2 :(得分:3)
如果您使用的是Postgres,则可以使用django-pg-utils
package作为不同值的总和。
from pg_utils import DistinctSum
income_posts.annotate(total=DistinctSum('amount')
答案 3 :(得分:1)
对于那些使用django 2.2 LTE的用户,只需复制为Sum实现不同的django 3.0 commit,就可以实现此行为:
https://github.com/django/django/commit/5f24e7158e1d5a7e40fa0ae270639f6a171bb18e
这种方式:
from django.db.models Sum
class SumDistinctHACK(Sum):
allow_distinct = True
现在您可以使用django 3.0语法:
queryset.annotate(
sum_result=SumDistinctHACK(
'relatedmodel__values_to_sum',
distinct=True,
)
)
如果升级到SumDistinctHACK
,请记住将Sum
替换为django >= 3.0
答案 4 :(得分:1)
对于旧版本的 Django,请使用 Func
queryset.annotate(
sum_result=Sum(
Func(F('amount'), function='DISTINCT')
)
)
答案 5 :(得分:0)
Django 3.0在Sum和Avg上引入了“ distinct = True”: https://docs.djangoproject.com/en/3.0/ref/models/querysets/#sum
答案 6 :(得分:0)
你可以这样做:
income_posts.values("category__name").distinct().annotate(total=Sum("amount"))
答案 7 :(得分:0)
我认为这个问题也与Combining multiple aggregations有关。
Here is the ticket 此错误。
我们可以使用 Subquery
(Django Docs) 来解决这个问题:
from django.db.models import Subquery, OuterRef, IntegerField, Sum, Value, Count
MyModel.objects.annotate(
count_model_a=Count('ModelA', distinct=True),
sum_model_b=Coalesce(
Subquery(
ModelB.objects.filter(
MyModel=OuterRef('pk')
).values('MyModel_id').annotate(
my_sum=Sum('MyModel_Field')
).values('my_sum')[:1],
output_field=IntegerField()
),
Value(0)
)
).values("count_model_a", "sum_model_b")
我还使用了 Coalesce
(Django Docs) 函数来防止返回 None
。
以上代码将对数据库运行一次查询。