就像@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() 交互。