就像@Alvaro 已经回答了 Django 的直接等效 forGROUP BY语句:
SELECT actor, COUNT(*) AS total
FROM Transaction
GROUP BY actor
是通过使用values()和annotate()方法如下:
Transaction.objects.values('actor').annotate(total=Count('actor')).order_by()
然而,还必须指出一件事:
如果模型在 中定义了默认排序class Meta,则该.order_by()子句对于正确的结果是强制性的。即使不打算订购,您也不能跳过它。
此外,对于高质量的代码,建议始终在.order_by()之后放置一个子句annotate(),即使没有class Meta: ordering. 这种方法将使声明面向未来:无论未来对class Meta: ordering.
让我给你举个例子。如果模型有:
class Transaction(models.Model):
actor = models.ForeignKey(User, related_name="actor")
acted = models.ForeignKey(User, related_name="acted", null=True, blank=True)
action_id = models.IntegerField()
class Meta:
ordering = ['id']
那么这种方法将不起作用:
Transaction.objects.values('actor').annotate(total=Count('actor'))
那是因为 DjangoGROUP BY在每个字段上都执行了附加操作class Meta: ordering
如果您要打印查询:
>>> print Transaction.objects.values('actor').annotate(total=Count('actor')).query
SELECT "Transaction"."actor_id", COUNT("Transaction"."actor_id") AS "total"
FROM "Transaction"
GROUP BY "Transaction"."actor_id", "Transaction"."id"
很明显,聚合不会按预期工作,因此.order_by()必须使用该子句来清除此行为并获得正确的聚合结果。
请参阅:与官方 Django 文档中的默认排序或 order_by() 交互。