几个模型的聚合 - Django

时间:2010-03-20 03:52:24

标签: python database django django-models

我正在尝试计算查询集的各个子集上字段的平均值。

Player.objects.order_by('-score').filter(sex='male').aggregate(Avg('level'))

这完美无缺!


但是...... 如果我尝试为前50名玩家计算它,那么它就不起作用了。

Player.objects.order_by('-score').filter(sex='male')[:50].aggregate(Avg('level'))

最后一个返回与上面的查询完全相同的结果,这是错误的。


我做错了什么?

非常感谢帮助!

3 个答案:

答案 0 :(得分:4)

topfifty = Player.objects.order_by('-score')[:50]
Player.objects.filter(sex='male',pk__in=topfifty).aggregate(avglevel=Avg('level'))

编辑:我没有测试过这个,但我想你会明白我要去哪里。

topfifty = Player.objects.order_by('-score')[:50]
ids = []
for t in topfifty:
    ids += [t.id]

Player.objects.filter(sex='male',pk__in=ids).aggregate(avglevel=Avg('level'))

这是一种hackish,但我能想到的最好。也许考虑过滤男性并选择前50名男性而不是前五名,然后过滤掉男性。

答案 1 :(得分:3)

将问题分解为两个逻辑步骤;找出目标集,执行汇总计算。

top50_male_players = Player.objects.filter(sex='male').order_by('-score')[:50]
result = Player.objects.filter(pk__in=top50_male_players).aggregate(Avg('level'))

由于对QuerySet的延迟评估,它将在单个数据库操作中执行。您可以在shell中使用它来验证查询计数。

> from django.db import connection
> connection.queries = []
> top50_male_players = Player.objects.filter(sex='male').order_by('-score')[:50]
> len(connection.queries)
0
> result = Player.objects.filter(pk__in=top50_male_players).aggregate(Avg('level'))
> len(connection.queries)
1
> result
{'level__avg': <some number>}
> len(connection.queries)
1

答案 2 :(得分:-1)

嗯。文档说

“切片。如限制查询集中所述,可以使用Python的数组切片语法对QuerySet进行切片。通常切片查询会返回另一个(未评估的)QuerySet,但如果使用”步骤“,Django将执行数据库查询切片语法的参数。“ http://docs.djangoproject.com/en/dev/ref/models/querysets/

所以我试试

Player.objects.order_by('-score').filter(sex='male')[0:50:1].aggregate(Avg('level'))