Django ORM注解Sum计算错误,其乘以条目数,是有线的。

问题描述 投票:0回答:1

我在Django ORM中遇到了一个有线的情况。它返回了一个错误的计算和意外地乘以我不想要的条目数,它的行为完全是有线的。

这些是我的模型

class Person(models.Model):
    name = models.CharField(max_length=100)



class Purchase(models.Model):
    person = models.ForeignKey(
        Person,
        on_delete=models.CASCADE,
        related_name='person_purchase'
    )

    amount = models.DecimalField(decimal_places=2, max_digits=5)



class Consumption(models.Model):
    person = models.ForeignKey(
        Person,
        on_delete=models.CASCADE,
        related_name='person_consumption'
    )

    amount = models.DecimalField(decimal_places=2, max_digits=5)

这是我的疑问。

person_wise_payable = Person.objects.annotate(
            difference=ExpressionWrapper(
                Coalesce(Sum('person_purchase__amount'), Value(0)) - Coalesce(Sum('person_consumption__amount'), Value(0)),
                output_field=FloatField()
            ),
        )

    for i in person_wise_payable:
        print(i.difference, i.name)

我想知道人的购买和消费之间的区别。

例如,我有3个人。foo, doe, jhon

而这些都是他们的作品

Purchase models entries:
foo = 5
doe = 2
doe = 3
doe = 3


Consumption models entries:

foo = 1
foo = 2
foo = 2
doe = 1
doe = 1
jhon = 2

所以你看上面。

foo total purchase is 5
doe total purchase is 8
jhon total purchase is 0 (coz, no entry of him)

foo total consumption is 5
doe total consumption is 2
jhon total consumption is 2

所以,如果我们减去预期的产出差额。consumptionpurchase

foo : 5 - 5 =   0
doe: 8 - 2 =   6
jhon: 0 - 2 =   -2

我希望你能明白我想做什么,预期的输出是什么。

foo 0, doe 6 and jhon -2

但问题是,我现在的查询没有返回上面这样的输出,而是返回非常非常多的有线,见下面的有线结果。

-2.0 jhon
10.0 doe
10.0 foo

谁能帮帮我,我怎么才能把它做对?我这几天都在努力,还不能实现这个功能

django django-models django-rest-framework django-orm
1个回答
2
投票

如果你做了多个JOINs,那么它们就像一个乘数,因为你做了一个查询。

SELECT SUM(purchase.amount) - SUM(consumption.amount)
FROM person
LEFT OUTER JOIN purchase
LEFT OUTER JOIN consumption

于是 一样 purchase.amount 重复的次数多了,因为有相关的 consumptions,以及 一样 consumption.amount 重复的次数多了,因为有相关的 purchases.

你可以用子查询来解决这个问题,例如用。

person_wise_payable = Person.objects.annotate(
    difference=Coalesce(Subquery(
        Purchase.objects.filter(
            person=OuterRef('pk')
        ).values('person').annotate(
            sum=Sum('amount')
        ).values('sum')[:1]
    ), Value(0)) - Coalesce(Subquery(
        Consumption.objects.filter(
            person=OuterRef('pk')
        ).values('person').annotate(
            sum=Sum('amount')
        ).values('sum')[:1]
    ), Value(0))
)
© www.soinside.com 2019 - 2024. All rights reserved.