Django简单的GROUP BY

时间:2013-07-29 09:43:46

标签: django django-models

我想为每个类别选择一本书,并计算每个类别的书籍数量

我的模特:

class Book(models.Model):
    title = models.CharField(max_length=100)
    category = models.CharField(max_length=100)

SQL应该类似于: SELECT title, COUNT(*) as total FROM book GROUP BY category

我试过使用注释方法

Book.objects.annotate(total_messages=Count('category'))

但它按book.id分组,所以我得到了所有书籍的清单,根本没有分组。

3 个答案:

答案 0 :(得分:2)

如果要指定分组字段,则应使用values()

Book.objects.values('category').annotate(total_messages=Count('title'))

这是它产生的查询:

>>> Book.objects.values('category').annotate(total_messages=Count('title')).query.__str__()
Out[11]: u'SELECT "my_app_book"."category", COUNT("my_app_book"."title") AS "total_messages" FROM "my_app_book" GROUP BY "my_app_book"."category"'

答案 1 :(得分:1)

试试这个:

Book.objects.values('category').annotate(total_messages=Count('title'))

答案 2 :(得分:1)

来自MySQL documentation

  

在标准SQL中,包含GROUP BY子句的查询不能引用选择列表中未在GROUP BY子句中命名的非聚合列。

这意味着在单个查询中实现所需内容的唯一方法是使用OUTER JOIN语句。据我所知,Django ORM不支持从表到自身的OUTER JOIN语句。

除了使用原始SQL语句之外,获得所需内容的唯一方法(包含该书类别中书籍数量的书籍列表)是使用2个单独的查询并在Python中处理它们。

qs = Book.objects.values('category').annotate(count=Count('id'))
count = dict([(x['category'], x['count']) for x in qs])
books = Book.objects.all()
for book in books:
    book.category_count = count['category']