Агрегация по нескольким моделям - Джанго - PullRequest
2 голосов
/ 20 марта 2010

Я пытаюсь вычислить среднее значение поля по различным подмножествам набора запросов.

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 ]

4 голосов
/ 20 марта 2010
topfifty = Player.objects.order_by('-score')[:50]
Player.objects.filter(sex='male',pk__in=topfifty).aggregate(avglevel=Avg('level'))

edit: я не проверял это, но я думаю, вы поняли, куда я иду.

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'))

Это немного хакерски, но лучшее, что я могу придумать. возможно, рассмотрите возможность фильтрации для мужчин и взятия 50 лучших мужчин вместо этого, который берет лучшие 50 и затем отфильтровывает мужчин.

3 голосов
/ 21 марта 2010

Разбейте проблему на два логических шага; выяснить целевой набор, выполнить совокупный расчет.

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 он будет выполнен за одну операцию с БД. Вы можете поиграть с этим в оболочке, чтобы проверить количество запросов.

> 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
0 голосов
/ 20 марта 2010

Хм. Документы говорят

"Slicing. Как объяснено в Ограничении QuerySets, QuerySet может быть нарезан, используя синтаксис 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'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...