使用 Django ORM 注释查询以计算 2 个表值的总和

Posted

技术标签:

【中文标题】使用 Django ORM 注释查询以计算 2 个表值的总和【英文标题】:Annotate query for calculate sum of 2 table value with Django ORM 【发布时间】:2019-03-26 14:23:58 【问题描述】:

我有两张桌子

Class Billing(models.Model):
 id=models.AutoField(primary_key=True)
 .....
 #Some more fields
 ....


Class BillInfo(models.Model):
  id=models.AutoField(primary_key=True)
  billing=models.ForeignKey(Billing)
  testId=models.ForeignKey(AllTests)
  costOfTest=models.IntegerField(default=0)
  concession=models.IntegerField(default=0)

这里BillInfo 是垂直表,即一个Billing 有多个BillInfo。在这里,我想计算单个BillingSum(costOfTest - concession)

我可以使用单个查询来实现吗?

需要帮助,提前致谢。

【问题讨论】:

BillInfoBillingForeignKey 是什么? 是的,问题已更新。 【参考方案1】:

你可以这样写:

from django.db.models import F, Sum

Billing.objects.annotate(
    the_sum=Sum(F('billinfo__costOfTest') - F('billinfo__concession'))
)

这里QuerySet 中的每个Billing 对象都将有一个额外的属性.the_sum,它是所有costOfTests 减去所有相关BillingInfoconcession 的总和对象。

计算此值的 SQL 查询大致如下:

SELECT billing.*
       SUM(billinginfo.costOfTest - billinginfo.concession) AS the_sum
FROM billing
LEFT OUTER JOIN billinginfo ON billinginfo.billing_id = billing.id
GROUP BY billing.id

因此,当您“实现”查询时,查询将在一次调用中获得所有Billing 对象的总和。

对于没有任何相关BillingInfoBilling对象,the_sum属性将为None,我们可以通过使用Coalesce [Django-doc]函数来避免这种情况:

from django.db.models import F, Sum, Value
from django.db.models.functions import Coalesce

Billing.objects.annotate(
    the_sum=Coalesce(
        Sum(F('billinfo__costOfTest') - F('billinfo__concession')),
        Value(0)
    )
)

【讨论】:

BillingInfo 具有 Billing 作为 ForeignKey。收到错误django.core.exceptions.FieldError: Cannot resolve keyword 'billinfo' into field. @GAJESHPANIGRAHI:确实,正如您在查询中看到的那样,我们在 JOIN 中使用了此外键的 billing_id 对应项。 @GAJESHPANIGRAHI:关键是如果你从模型AB 定义一个ForeignKey,Django 会构造一个从B 引用的隐式 关系到A 但我想从Billing 模型访问BillInfo,而BillingBillInfo 的ForeignKey。有一个对象billinginfo_set @GAJESHPANIGRAHI:我们正在Billing 访问BillingInfo。注意F('billinginfo__...')ForeignKey 位于其他位置的事实 很重要,因为数据库会生成JOIN,并且通常会有适当的索引来正确执行此操作。并不是因为数据库中没有explicitForeignKey,所以获取relatedBillingInfo的集合是个问题。

以上是关于使用 Django ORM 注释查询以计算 2 个表值的总和的主要内容,如果未能解决你的问题,请参考以下文章

用 Django ORM 中的前一个对象注释查询集

Django ORM distinct 查询,其中订单由带注释的字段完成,您需要 distinct('id')

Django ORM注释Sum计算错误及其乘以条目数,它是有线的

Django ORM分别查询正负值的总和

通过 Django ORM 重命名嵌套注释字段

是否可以将 SQL 注释添加到使用 ORM 构建的查询中?