Django subquery with aggregate

后端 未结 3 1568
孤街浪徒
孤街浪徒 2021-01-19 18:27

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

相关标签:
3条回答
  • 2021-01-19 19:10

    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'))
    
    0 讨论(0)
  • 2021-01-19 19:10

    For using the subquery, use this:

    query=User.objects.annotate(total_spent=Subquery(subquery.values("user")[:1])).order_by("total_spent")
    
    0 讨论(0)
  • 2021-01-19 19:28

    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:

    1. It can't be evaluated before it is used

    2. 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.

    0 讨论(0)
提交回复
热议问题