Django聚合并注释为按组计数-多级



我有一个模型,看起来像:

class Foo(models.Model):
bar = models.CharField(...)
baz = models.CharField(...)
Foo(bar="a", baz="x")
Foo(bar="a", baz="x")
Foo(bar="a", baz="y")
Foo(bar="b", baz="y")

我想要一个查询集,它将为每个bar:返回最大计数的唯一(bar, baz)

[
{"bar": "a", "baz": "x", "count": 2},
{"bar": "b", "baz": "y", "count": 1},
]

理想情况下,这一切都将在一个查询中完成,我尝试过distinctaggregateannotate的组合,但都没有成功,除了运行我想避免的原始SQL之外,我看不到如何做到这一点。

我使用PostgreSQL作为我的数据库后端。

Django的数据库抽象API非常强大,而且我经常发现即使是最复杂的查询也可以获得必要的结果。一开始可能会让人感到困惑,但如果使用得当,可以通过注释获得很多效果。

https://docs.djangoproject.com/en/4.0/topics/db/aggregation/#values

我能够用DjangovaluesannotateCount:实现结果

from django.db.models import Count
from .models import Foo
Foo.objects.all().values('bar','baz').annotate(count=Count('id')).order_by('-count')

更新上面的答案忽略了问题结果必须为每个bar返回最大计数的唯一(bar,baz(对这一点。

虽然我还不能过滤下面的结果,但我可以使用WindowRowNumber表达式返回一个row_number密钥。然后可以在模板中过滤row_number==1,但我认为这不是最好的方法。

from django.db.models import F, Count
from django.db.models.expressions import Window
from django.db.models.functions import RowNumber
Foo.objects.all().values('bar','baz')
.annotate(count=Count('id')).order_by('-count')
.annotate(
row_number=Window(
expression=RowNumber(),
partition_by=[F('bar')],
order_by=F('count').desc()))

最新更新