Django эквивалент COUNT с GROUP BY - PullRequest
30 голосов
/ 09 мая 2009

Я знаю, что в Django 1.1 есть несколько новых методов агрегирования. Однако я не смог найти эквивалент следующего запроса:

SELECT player_type, COUNT(*) FROM players GROUP BY player_type;

Возможно ли это с помощью API запросов модели Django 1.1, или я должен просто использовать простой SQL?

Ответы [ 2 ]

60 голосов
/ 09 мая 2009

Если вы используете бета-версию Django 1.1 (транк):

Player.objects.values('player_type').order_by().annotate(Count('player_type'))
  • values('player_type') - только для включения поля player_type в предложение GROUP BY.
  • order_by() - для исключения возможного порядка по умолчанию, который может привести к включению ненужных полей в SELECT и GROUP BY.
15 голосов
/ 09 мая 2009

Django 1.1 поддерживает такие методы агрегации, как count. Вы можете найти полную документацию здесь .

Чтобы ответить на ваш вопрос, вы можете использовать что-то вроде:

from django.db.models import Count
q = Player.objects.annotate(Count('games'))
print q[0]
print q[0].games__count

Это потребует небольшой настройки в зависимости от вашей реальной модели.

Редактировать: приведенный выше фрагмент генерирует агрегации для каждого объекта. Если вы хотите выполнить агрегацию для определенного поля в модели, вы можете использовать метод values:

from django.db.models import Count
q = Player.objects.values('playertype').annotate(Count('games')).order_by()
print q[0]
print q[0].games__count

order_by() необходимо, потому что поля в порядке по умолчанию выбираются автоматически, даже если они явно не переданы в values(). Этот вызов order_by() очищает любой порядок и заставляет запрос вести себя как ожидалось.

Также, если вы хотите сосчитать поле, используемое для группировки (эквивалентно COUNT(*)), вы можете использовать:

from django.db.models import Count
q = Player.objects.values('playertype').annotate(Count('playertype')).order_by()
print q[0]
print q[0].playertype__count
...