我使用一个事务模型来跟踪系统中发生的所有事件
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()
......
如何在我的系统中获得前5名演员?
在sql中它基本上是
SELECT actor, COUNT(*) as total
FROM Transaction
GROUP BY actor
ORDER BY total DESC
4条答案
按热度按时间ubof19bj1#
根据文档,您应该用途:
values():指定哪些列将用于“分组依据”
Django文档:
使用values()子句约束结果集中返回的列时,计算注解的方法略有不同。原始QuerySet中的每个结果都不是返回带注解的结果,而是根据values()子句中指定的字段的唯一组合对原始结果进行分组。
public void run():指定对分组值的运算
Django文档:
生成摘要值的第二种方法是为QuerySet中的每个对象生成独立的摘要,例如,如果你正在检索一个图书列表,你可能想知道有多少作者为每本书做出了贡献,每本书与Author有多对多的关系;我们想为QuerySet中的每本书总结这种关系。
可以使用annotate()子句生成每个对象的摘要。当指定annotate()子句时,QuerySet中的每个对象都将使用指定的值进行注解。
顺序由子句是自我解释的。
总结如下:您可以通过分组生成作者的查询集,添加注解(这将为返回值添加一个额外的字段),最后,您可以通过此值对它们进行排序
有关详细信息,请参阅https://docs.djangoproject.com/en/dev/topics/db/aggregation/
值得注意的是:如果使用Count,传递给Count的值不会影响聚合,只会影响最终值的名称。聚合器按值的唯一组合(如上所述)分组,而不是按传递给Count的值分组。以下查询相同:
u7up0aaq2#
就像@Alvaro回答了Django直接对应的
GROUP BY
语句:是通过使用
values()
和annotate()
方法,如下所示:但还有一点必须指出:
**如果模型在
class Meta
中定义了默认顺序,则.order_by()
子句是必需的,以获得正确的结果。**即使没有指定顺序,也不能跳过它。此外,对于高质量的代码,建议始终在
annotate()
之后放置.order_by()
子句,即使没有class Meta: ordering
。这种方法将使声明面向未来:无论将来对class Meta: ordering
进行任何更改,它都将按预期工作。让我给你举个例子。如果模型有:
这样的方法是行不通的:
这是因为Django对
class Meta: ordering
中的每个字段执行额外的GROUP BY
如果要打印查询:
很明显,聚合不会按预期工作,因此必须使用
.order_by()
子句来清除此行为并获得正确的聚合结果。参见:与默认排序或order_by()的交互在Django官方文档中。
vybvopom3#
如果你想反向(从大值到小值),只需使用
-
minus。f1tvaqid4#
实际上,我没有使用values()和annotations合并。
下面写的代码在我尝试的时候没有工作
所以,我更喜欢下面的类型代码分组。