如何在 Django 中通过 group by 获得额外的列?

Posted

技术标签:

【中文标题】如何在 Django 中通过 group by 获得额外的列?【英文标题】:How to get extra columns in group by in Django? 【发布时间】:2020-08-23 17:40:09 【问题描述】:

我只想在带有值的注释结果中包含ID(和其他字段)(即分组依据)。

我会用一个例子来解释(以下只是一个例子,请不要相信这个坏模型),

class Book(models.Model):
    name = models.CharField()
    version = models.IntegerField() # Assming its just a number that increments when each version is published like 1...2...3 and so on.
    published_on = models.DateTimeField()
    author = models.ForeignKey(User)

class Text(models.Model):
    book_text = models.ForeignKey(Book)

我想要的是一本书的最大版本(或多个版本),我通过

Book.objects.values('name', 'author').annotate(Max('version'))


**Generated SQL (mysql) query**:
SELECT "name",
       "author",
       Max("version") AS "version__max" 
FROM   "book" 
GROUP  BY "name",
          "author" 

但是上面的结果不包含IDpublished_on 如果我将它们添加到它所分组的值中,这不是我想要的。我只想按nameauthor 分组,但想要其他字段或至少获得一个ID。

Expected SQL:
SELECT "id",
       "published_on",
       "name",
       "author",
       Max("version") AS "version__max" 
FROM   "book" 
GROUP  BY "name",
          "author" 

【问题讨论】:

【参考方案1】:

在 SQL 中,您不能选择不在 group by 语句中的字段。您应该通过附加查询获取 id,例如:

Book.object.filter(name=name_from_first_query, author=author_from_first_query, version=version_from_first_query

当然,您必须通过查询遍历您的组的结果。

【讨论】:

是的,你是对的,我想我必须使用 python 或 Subquery... 一个很好的解释我发现为什么建议在 select 和 group by 中使用相同的字段是here link ...但非常感谢。【参考方案2】:
from django.db.models import F

Book.objects.values('name', 'author').annotate(Max('version'), id=F('id'))

在 django 中进行分组时。顺序很重要。我们传递需要通过查询集分组的值,并在注释函数中使用 F 表达式添加结果查询集中所需的额外元素。如果我们在值中添加id,那么在进行分组时会考虑到它。 希望这可以清除:)

【讨论】:

虽然这段代码可能会解决问题,但一个好的答案还应该解释代码的什么以及它如何提供帮助。 所以这个方案看起来不错,发帖前我也试过了。但不知何故它不起作用......ID 被添加到 GROUP BY 查询中,并且像 Book.objects.values('name', 'author','id').annotate(Max('version')) 虽然此代码可能提供问题的解决方案,但强烈建议您提供有关此代码为何和/或如何回答问题的附加上下文。从长远来看,只有代码的答案通常会变得毫无用处,因为未来遇到类似问题的观众无法理解解决方案背后的原因。 添加解释以便更好地理解 :) 点赞【参考方案3】:
Book.objects.values('name', 'author').annotate(Max('version'), Max('id'))

【讨论】:

这个解决方案有效,但看起来很老套,但无论如何......谢谢。 虽然此代码可能提供问题的解决方案,但强烈建议您提供有关此代码为何和/或如何回答问题的附加上下文。从长远来看,只有代码的答案通常会变得毫无用处,因为未来遇到类似问题的观众无法理解解决方案背后的原因。

以上是关于如何在 Django 中通过 group by 获得额外的列?的主要内容,如果未能解决你的问题,请参考以下文章