是否可以使用django ORM对GROUP BY进行聚合查询?

时间:2016-06-24 07:59:55

标签: python django django-orm

我正在尝试计算SELECT SUM(...) FROM ... GROUP BY ...的等价物。这是一个简化的类比:

让我们说Salesperson个对象卖东西,并通过每个Sale产生的保证金获得佣金:

sp = Salesperson.objects.get(pk=1)
my_sales = Sale.objects.filter(fk_salesperson=sp)

#calculate commission owing to sp
commission = 0
for sale in my_sales:
    commission += sp.commission_rate\
                     * (sale.selling_price - sale.cost_price)

最后一个循环可以通过以下方式完成:

.annotate( commission= ( F('selling_price')-F('cost_price') )\
                            * sp.commission_rate )

但是我可以进一步聚合所有Salesperson个对象的查询吗?即我想知道每个销售人员的佣金(即大约SELECT SUM( (sale_price-cost_price) * commission_rate) FROM Sales GROUP BY Salesperson)。我可以做类似下面的事情,但我试图用ORM来做:

commissions = []
salespeople = Salesperson.objects.all()
for sp in salespeople:
    data = Sale.objects.filter(fk_salesperson=sp)\
       .annotate(salesperson=F('sp__email')\
       .annotate(commission= ( F('selling_price')-F('cost_price') )\
                                 * sp.commission_rate )
    commissions.append(data)

有没有办法通过单个查询(使报告数据库服务器完成工作)而不是在我的应用程序服务器上执行此操作?

1 个答案:

答案 0 :(得分:2)

Sum()中可以使用django.db.models聚合函数,您可以使用F表达式中的相关字段。

from django.db.models import F, Sum

Sales.objects.values('salesperson__id').annotate(commission=Sum(
    (F('selling_price') - F('cost_price')) * F('salesperson__commission_rate')
))