Django编程错误:必须在GROUP BY子句中出现或用于聚合函数。

4

假设有一个基础模型,比如:

class Post(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(_('Title'), max_length=100)
    content = models.TextField(_('Content html'), max_length=65000)
    author = models.ForeignKey('user.User', on_delete=models.SET_NULL)

Post.objects.annotate(Count('id'))这样的查询(或任何字段,任何注释)会导致以下错误:

ProgrammingError: column "post.created" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "post"."id", "post"."created", "post"."ti...

使用django 1.11.16和postgres 9.4.19。阅读了另一个stackoverflow问题,尝试了不同的django版本和postgres版本,使用django 2.0、2.1.2和postgres 9.5仍然出现相同的错误!阅读周围的资料,发现可能是与SQL相关的问题,但我只在运行Ubuntu 18.04(bionic)的一个服务器上遇到了这个问题。在我的本地系统中,使用django 1.11.16或任何版本以上的版本和postgres 9.4或以上的版本运行查询都可以正常运行,因此问题可能实际上与某些底层库有关,我没有运行复杂的查询,任何简单的annotate()在Ubuntu 18.04上与postgres 9.4或9.5一起使用都会失败 [更新]如果你处于这种情况而且不知道发生了什么,请验证涉及的表是否已经创建了索引。我的问题最终变成了posts表没有PRIMARY KEY定义或其他限制,这是在pg_restore中失败的,导致所有数据和一些模式定义被还原,是的,你没看错,一些其他的模式定义缺失了,不知道为什么。但是,我没有尝试调试发生了什么事情,而是在空数据库上运行了一个初始的python manage migrate以便正确创建模式并进行验证(psql -d <db_name> -c '\d posts'),然后再次使用--data-only--disable-triggers标志运行pg_restore,最终我成功地还原了模式和数据,并且查询也可以正常工作。

你能发布 print(Post.objects.annotate(Count('id')).query) 的输出吗?那将是你的查询集的 SQL 查询。 - Håken Lid
注释时计算id没有太多意义,因为每一行都包含一个记录,因此计数始终为1(如果是NULL则为0)。 - Willem Van Onsem
@WillemVanOnsem:确实如此。但这并不解释为什么他们会出现这个SQL错误。 - Håken Lid
因此,您链接的问题的结论是,此错误特定于由数据库视图支持而不是数据库表支持的模型。如果您只在生产数据库中遇到此错误,则应调查数据库架构并查找生产数据库和开发数据库之间的任何差异。 - Håken Lid
嘿,大家好,我会在这里更新我的问题;就目前而言,据我所知,如果您实际上在ID上有索引,则仅对ID进行GROUP BY而不引用SELECT的其他字段是有效的..结果证明,在进行pg_restore之后,由于某种奇怪的原因(我未能发现),数据已恢复,但某些(不是全部)模式定义丢失了..因此,例如帖子表没有主键语句,因此该注释失败。 - AguD
[UPDATE] 对我有效。 - amolbk
2个回答

2
那个错误信息是因为当查询中有聚合函数时,PostgreSQL不会猜测非分组列该怎么处理。这是Django ORM手势过多的情况之一,它允许我们自己给自己惹麻烦。
我在我的使用Django 2.1和另一个使用1.11的项目上运行了一个测试,使用Model.objects.annotate(Count('id'))没有问题。如果你发布完整的QuerySet,人们将能够更进一步地帮助你。

谢谢@schillingt!是的,有时在抽象层中有太多的魔法会使得在边缘情况下进行调试变得复杂:/ 我发现问题所在,当使用pg_restore还原转储时,表没有模式,数据存在但表没有索引、约束、主键.. 这就是导致查询失败的问题,为什么pg_restore无法还原某些(而不是全部)表的模式.. 想出了一个解决方法,在尝试调试pg_restore之前采用这种方式。 - AguD

2

我遇到了问题,但我解决了它。 你应该在ORM后面添加.order_by("xxx")

之前:

search_models.Author.objects.values("first_institution", "institution_code").annotate(
    counts=Count("first_institution")
)

之后:

search_models.Author.objects.values("first_institution", "institution_code").annotate(
    counts=Count("first_institution")
).order_by("-counts")

这对我有用,也希望能帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接