2016-06-24 66 views
3

我正试图计算SELECT SUM(...) FROM ... GROUP BY ...的等效值。这里有一个简单的比喻:是否有可能通过django ORM GROUP BY聚合查询?

假设Salesperson对象是卖东西,让他们通过每个Sale产生的保证金佣金:

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

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) 

这最后的循环可能会喜欢的东西来完成

但是,我可以进一步汇总所有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) 

有没有办法使用单个查询(使报告数据库服务器做的工作),而不是做它这样做在我的应用服务器上?

回答

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') 
)) 
+0

谢谢,不幸的是,您的解决方案并不了解问题的本质。该示例是故意构造的,因此Salesperson模型中没有相关字段“sales”。 (这是合乎逻辑的:销售应该是指向销售人员的外键,而不是其他方式)。该示例的目的是找到一个解决方案来查询'Sale',然后将相关字段外键分组为'Sale',名为“'fk_salesperson'”。 – Escher

+1

有**是一种关系,虽然是隐含的。这是一种反向关系。 https://docs.djangoproject.com/en/1.9/topics/db/queries/#backwards-related-objects –

+0

我建议设置['related_name'](https://docs.djangoproject.com/en /1.9/ref/models/fields/#django.db.models.ForeignKey.related_name)属性为每个ForeignKey指定一个有意义的名称。如果你没有设置,我认为它应该是'sale_set__'而不是'sales__'。 –