我正在尝试计算查询集的各个子集上字段的平均值。
Player.objects.order_by('-score').filter(sex='male').aggregate(Avg('level'))
这完美无缺!
但是...... 如果我尝试为前50名玩家计算它,那么它就不起作用了。
Player.objects.order_by('-score').filter(sex='male')[:50].aggregate(Avg('level'))
最后一个返回与上面的查询完全相同的结果,这是错误的。
我做错了什么?
非常感谢帮助!
答案 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'))