Django ORM 注释 Sum 计算错误及其乘以条目数,它是有线的
Django ORM annotate Sum calculation wrong and its multiplying by number of entry, it's wired
我正在处理 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
如果我们从 purchase
中减去 consumption
,那么预期 output/difference
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
任何人都可以帮助我如何正确完成它?最近几天我一直在苦苦挣扎,还没有实现
如果您进行多个 JOIN,它们将充当乘数,因为您进行了查询
SELECT SUM(purchase.amount) - SUM(consumption.amount)
FROM person
LEFT OUTER JOIN purchase
LEFT OUTER JOIN consumption
所以 same purchase.amount
重复了很多次,因为有相关的 consumption
s,并且 same consumption.amount
重复了很多次,因为有相关的 purchase
s.
您可以使用子查询解决此问题,例如:
person_wise_payable = Person.objects.annotate(
difference=Coalesce(<b>Subquery(</b>
Purchase.objects.filter(
person=OuterRef('pk')
).values('person').annotate(
sum=Sum('amount')
).values('sum')[:1]
<b>)</b>, Value(0)) - Coalesce(<b>Subquery(</b>
Consumption.objects.filter(
person=OuterRef('pk')
).values('person').annotate(
sum=Sum('amount')
).values('sum')[:1]
<b>)</b>, Value(0))
)
我正在处理 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
如果我们从 purchase
consumption
,那么预期 output/difference
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
任何人都可以帮助我如何正确完成它?最近几天我一直在苦苦挣扎,还没有实现
如果您进行多个 JOIN,它们将充当乘数,因为您进行了查询
SELECT SUM(purchase.amount) - SUM(consumption.amount)
FROM person
LEFT OUTER JOIN purchase
LEFT OUTER JOIN consumption
所以 same purchase.amount
重复了很多次,因为有相关的 consumption
s,并且 same consumption.amount
重复了很多次,因为有相关的 purchase
s.
您可以使用子查询解决此问题,例如:
person_wise_payable = Person.objects.annotate(
difference=Coalesce(<b>Subquery(</b>
Purchase.objects.filter(
person=OuterRef('pk')
).values('person').annotate(
sum=Sum('amount')
).values('sum')[:1]
<b>)</b>, Value(0)) - Coalesce(<b>Subquery(</b>
Consumption.objects.filter(
person=OuterRef('pk')
).values('person').annotate(
sum=Sum('amount')
).values('sum')[:1]
<b>)</b>, Value(0))
)