Django ProgrammingError должен появиться в предложении GROUP BY или использоваться в агрегатной функции.

Дайте ему любую базовую модель, скажем;

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.

Как я прочитал здесь в другом вопросе о переполнении стека пробовал разные версии django и версии postgres; используя django 2.0, 2.1.2, postgres 9.5.. та же ошибка! Читая, я видел, что это может быть проблема, связанная с SQL, но у меня эта проблема только на одном сервере с Ubuntu 18.04 (bionic). Выполнение запроса локально в Ubuntu 16.04, с django 1.11.16 или любой версией выше и postgres 9.4 или выше работает нормально в моей локальной системе. Таким образом, проблема может быть связана с каким-то низким уровнем возможно, библиотеки, я не запускаю сложные запросы, любой простой annotate() с django 1.11+ не работает в Ubuntu 18.04 с postgres 9.4 или 9.5

[ОБНОВЛЕНИЕ] Может быть полезно для вас, если вы обнаружите, что находитесь в этом сценарии и не понимаете, что происходит, убедитесь, что для рассматриваемой таблицы созданы индексы. Моя проблема оказалась в том, что таблица posts не имела ни определения PRIMARY KEY, ни каких-либо других ограничений, сбой в pg_restore, который восстановил все данные и некоторые определения схемы, да, вы правильно прочитали, какая-то другая схема определения отсутствовали, понятия не имею, почему.. Но вместо того, чтобы пытаться отлаживать то, что произошло с pg_restore, я запустил начальный python manage migrate в пустой БД, чтобы на этот раз схема была правильно создана и проверена (psql -d <db_name> -c '\d posts' ), затем снова запустите pg_restore с флагами --data-only и --disable-triggers. Итак, наконец, я правильно восстановил схему и данные, и запрос сработал.


person AguD    schedule 24.10.2018    source источник
comment
Можете ли вы опубликовать вывод print(Post.objects.annotate(Count('id')).query)? Это будет запрос sql из вашего набора запросов.   -  person Håken Lid    schedule 24.10.2018
comment
Нет особого смысла считать ids при аннотировании, так как каждая строка содержит одну запись, и, следовательно, счетчик всегда 1 (или 0 в случае NULL.   -  person Willem Van Onsem    schedule 24.10.2018
comment
@WillemVanOnsem: Это правда. Но это не объясняет, почему они получают эту ошибку SQL.   -  person Håken Lid    schedule 24.10.2018
comment
Таким образом, вывод в вопросе, который вы связали, заключается в том, что эта ошибка характерна для моделей, поддерживаемых представлением базы данных, а не таблицей базы данных. Если вы получаете эту ошибку только в своей производственной базе данных, вам следует изучить схему базы данных и найти любые различия между производственной базой данных и базой данных разработки.   -  person Håken Lid    schedule 24.10.2018
comment
Привет, ребята, я обновлю свой вопрос здесь; Да, насколько я понимаю на данный момент, только идентификатор GROUP BY без ссылки на другие поля SELECT работает, если у вас действительно есть индекс по идентификатору.. оказывается, что после pg_restore по какой-то странной причине (что я не смог раскрыть) данные были восстановлены, но некоторые (не все) определения схемы отсутствовали.. поэтому, например, в таблице сообщений не было оператора PRIMARY KEY, и, таким образом, аннотация не удалась   -  person AguD    schedule 25.10.2018
comment
[ОБНОВЛЕНИЕ] сработало для меня.   -  person amolbk    schedule 26.07.2021


Ответы (2)


Это сообщение об ошибке связано с тем, что PostgreSQL не делает предположений о том, что делать с несгруппированными столбцами, когда в запросе есть агрегатная функция. Это один из случаев, когда Django ORM слишком сильно машет руками и позволяет нам выстрелить себе в ногу.

Я проверил свои проекты, использующие Django 2.1, и другой, использующий 1.11 с Model.objects.annotate(Count('id')), без проблем. Если вы опубликуете полный QuerySet, люди смогут помочь вам в дальнейшем.

person schillingt    schedule 24.10.2018
comment
Спасибо @schillingt! Да, иногда слишком много магии в слое абстракции усложняет отладку в крайних случаях :/ Я понял, в чем проблема, у таблицы не было схемы при восстановлении дампа с помощью pg_restore, данные были, но у таблицы не было индексов, никаких ограничений, первичные ключи.. Это была проблема, из-за которой запрос здесь не удался, почему pg_restore не удалось восстановить схему некоторых * (не всех) таблиц.. понятия не имею.. Разработал обходной путь и пошел по этому пути, прежде чем пытаться отладить pg_restore - person AguD; 25.10.2018

Я встретил проблему и решил ее. вы должны добавить .order_by("xxx") следуйте своему ORM!

до:

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')

Это сработало для меня, также желаю вам помочь.

person bode liang    schedule 08.06.2021