在Django ORM中,是否可以使用GROUP BY对聚合查询进行分组?

3
我将尝试计算等效于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个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
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')
))

谢谢,不幸的是你的解决方案没有理解问题的本质。这个例子是故意构造的,因为在Salesperson模型中没有相关领域“sales”。(这是合乎逻辑的:销售应该是指向销售人员的外键,而不是反过来)。这个例子的目的是找到一个解决方案,在Sale上进行查询,然后按照与Sale的外键称为“fk_salesperson”相关的字段分组。 - Escher
1
虽然隐含,但确实存在一种关系。这是一种反向关系。https://docs.djangoproject.com/en/1.9/topics/db/queries/#backwards-related-objects - Antoine Pinsard
我建议为每个ForeignKey设置related_name属性,以便给它一个有意义的名称。如果您没有设置一个,我认为它应该是sale_set__而不是sales__ - Antoine Pinsard
1
这似乎不是简单 SQL 查询的好的逻辑翻译 (SELECT SUM( (sale_price-cost_price) * commission_rate) FROM Sales GROUP BY Salesperson)。是否有更符合 Python 风格的方式,更好地反映原始 SQL 的简洁性? - Escher
你是对的,我修正了我的解决方案,从Sales开始而不是Salesperson。 - Antoine Pinsard
Merci bien mon ami - Escher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,