2

I have 2 tables

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)

Here BillInfo is verticle table i.e one Billing has multiple BillInfo. Here I want to calculate the Sum(costOfTest - concession) for a single Billing.

Can I achieve this using single query?

Need help, Thanks in advance.

2
  • What is the ForeignKey from BillInfo to Billing? Commented Oct 22, 2018 at 13:27
  • Yes, question updated. Commented Oct 22, 2018 at 13:28

1 Answer 1

4

You can write this as:

from django.db.models import F, Sum

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

Here every Billing object in this QuerySet will have an extra attribute .the_sum which is the sum of all costOfTests minus the concession of all related BillingInfo objects.

The SQL query that calculates this will look, approximately as:

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

So when you "materialize" the query, the query will obtain the sum for all the Billing objects in a single call.

For Billing objects without any related BillingInfo, the the_sum attribute will be None, we can avoid that by using the Coalesce [Django-doc] function:

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)
    )
)
Sign up to request clarification or add additional context in comments.

5 Comments

BillingInfo has Billing as a ForeignKey. Getting error django.core.exceptions.FieldError: Cannot resolve keyword 'billinfo' into field.
@GAJESHPANIGRAHI: indeed, and as you can see in the query, we make use of the billing_id counterpart of this foreign key in the JOIN.
@GAJESHPANIGRAHI: the point is that if you define a ForeignKey from model A to B, Django constructs an implicit relation that refers from B to A.
But I want to access the BillInfo from the Billing model and Billing is ForeignKey of BillInfo. There is an object billinginfo_set.
@GAJESHPANIGRAHI: we are accessing the BillingInfo from the Billing. Notice the F('billinginfo__...'). The fact that the ForeignKey is located otherwise does not matter, since a database makes a JOIN and will normally have a proper index to do this properly. It is not because there is no explicit ForeignKey stored in the database that this is a problem to obtain the set of related BillingInfo.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.