【问题标题】:Django simple GROUP BYDjango 简单的 GROUP BY
【发布时间】:2013-07-29 09:43:46
【问题描述】:

我想为每个类别选择一本书并获取每个类别中的书籍数量

我的模特:

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

我尝试过使用annotate方法

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

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

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    如果你想指定分组字段,你应该使用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"'
    

    【讨论】:

    • 这不会返回 book.title 和 book.pk。有什么方法可以添加吗?
    • 请记住,您已要求查询数据按类别分组。答案中的查询与您尝试获得的查询相同,不是吗?
    • 仅供参考,对于每个类别,您将有多个书名和书 ID。
    【解决方案2】:

    试试这个:

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

    【讨论】:

    • 这不会返回 book.title 和 book.pk。有什么方法可以添加吗?
    • 您需要另一个查询来执行此操作。另一种选择是使用 Q 对象或原始查询(不推荐)
    【解决方案3】:

    来自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']
    

    【讨论】:

      猜你喜欢
      • 2014-08-04
      • 1970-01-01
      • 2013-06-19
      • 1970-01-01
      • 2021-08-01
      • 2019-02-28
      • 2021-08-01
      • 2012-10-31
      • 2017-12-23
      相关资源
      最近更新 更多