【问题标题】:Django - Annotating multiple Sum() object gives wrong resultDjango - 注释多个 Sum() 对象会给出错误的结果
【发布时间】:2020-06-23 03:33:16
【问题描述】:

models.py 看起来像这样

class Channel(Model):
    name = CharField()

class Contract(Model):
    channel = ForeignKey(Channel, related_name='contracts')
    fee = IntegerField()

class ContractPayment(Model):
    contract = ForeignKey(Contract, related_name='payments')
    value = IntegerField()

当我查询模型时:

Channel.objects.annotate(pay=Sum('contracts__fee'))

返回:75000。它是正确的,但是当我这样查询时:

Channel.objects.annotate(pay=Sum('contracts__fee'))
               .annotate(paid=Sum('contracts__payments__value'))


它返回:支付:96000,支付:33000。如您所见,pay 已更改。这里发生了什么?我读了票#10060 但没有运气。

【问题讨论】:

  • Hopefull 在 Django 3.0 中为 Sum 添加了一个标志 distinct
  • 我试过distinct,但Contract 模型有很多相同的费用,所以我不能在这里使用distinct
  • 是的。那是不同的问题
  • 可以接受两次查询吗?

标签: django django-models django-queryset


【解决方案1】:

使用两个查询来获得想要的结果:

Channel.objects.annotate(pay=Sum('contracts__fee'))

Channel.objects.annotate(paid=Sum('contracts__payments__value'))

【讨论】:

  • 如果我想区分 paypaid 怎么办。例如:qs.annotate(diff=F('pay') - F('paid'))
【解决方案2】:

我认为您必须在annotate() 中使用distinct=True,如下所示...

Channel.objects.annotate(pay=Sum('contracts__fee', distinct=True)).annotate(paid=Sum('contracts__payments__value', distinct=True))

【讨论】:

  • 你试试这个吗?
  • 我试过了,因为ContractContractPayment 模型有很多相同的费用
  • 你有解决方案还是还在寻找?
  • 我通过不同的查询来实现这一点。但是这个问题还是可以接受的
【解决方案3】:

如果您不使用 Django3,我认为这应该可以:

from django.db.models import Subquery, OuterRef, Sum
contracts = Contract.objects.filter(channel__id=OuterRef("id")).values("fee")
tot = contracts.values("channel_id").annotate(total=Sum("fee")).values("total")
Channel.objects.annotate(pay=Subquery(tot), paid=Sum('contracts__payments__value')).values()

【讨论】:

    猜你喜欢
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    相关资源
    最近更新 更多