I have two models called User
and Transaction
. Here i want to get the all the users with total sum of the transaction amount where status is succe
You can hit this query:
from django.db.models import Avg, Count, Min, Sum
User.objects.filter(status="success").annotate(total_amount=Sum('transaction__amount'))
For using the subquery, use this:
query=User.objects.annotate(total_spent=Subquery(subquery.values("user")[:1])).order_by("total_spent")
This is made a lot easier with the django-sql-utils package.
from django.db.models import Sum,
from sql_util.utils import SubqueryAggregate
User.objects.annotate(
total_spend=SubqueryAggregate('transaction__amount',
filter=Q(status='success'),
aggregate=Sum)
)
If you want to do it the long way (without django-sql-utils), you need to know these two things about the subquery:
It can't be evaluated before it is used
It can only return a single record with a single column
So, you can't call aggregate
on the subquery, because this evaluates the subquery immediately. Instead you have to annotate the value. You also have to group by the outer ref value, otherwise you'll just annotate each Transaction independently.
subquery = Transaction.objects.filter(
status='success', user=OuterRef('pk')
).values(
'user__pk'
).annotate(
total_spend=Sum('amount')
).values(
'total_spend'
)
The first .values
causes the correct group by. The second .values
causes selecting the one value that you want.