Django - 注释多个 Sum() 对象会给出错误的结果
Posted
技术标签:
【中文标题】Django - 注释多个 Sum() 对象会给出错误的结果【英文标题】:Django - Annotating multiple Sum() object gives wrong result 【发布时间】: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
。
你看到***.com/questions/56567841/…了吗?
是的。那是不同的问题
可以接受两次查询吗?
【参考方案1】:
使用两个查询来获得想要的结果:
Channel.objects.annotate(pay=Sum('contracts__fee'))
和
Channel.objects.annotate(paid=Sum('contracts__payments__value'))
【讨论】:
如果我想区分pay
和 paid
怎么办。例如: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))
【讨论】:
你试试这个吗? 我试过了,因为Contract
和ContractPayment
模型有很多相同的费用
你有解决方案还是还在寻找?
我通过不同的查询来实现这一点。但是这个问题还是可以接受的【参考方案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()
【讨论】:
以上是关于Django - 注释多个 Sum() 对象会给出错误的结果的主要内容,如果未能解决你的问题,请参考以下文章