Почему Django ORM добавляет не указанное поле в предложение GROUP BY - PullRequest
0 голосов
/ 30 октября 2019

Я хочу выполнить этот запрос с помощью ORM:

SELECT ARRAY_AGG("wcm_workflows_transition"."name") AS "names"
FROM "wcm_workflows_transition"
GROUP BY "wcm_workflows_transition"."workflow_id"
ORDER BY "wcm_workflows_transition"."name" ASC;

. Для этого я использую

Transition.objects.values("workflow__id").annotate(names=ArrayAgg("name")).values("names")

Но по некоторым неизвестным причинам Джанго добавляет "wcm_workflows_transition"."name" к GROUP BY предложение.
Таким образом, запрос, выполненный предыдущим выражением Django ORM:

SELECT ARRAY_AGG("wcm_workflows_transition"."name") AS "names"
FROM "wcm_workflows_transition"
GROUP BY "wcm_workflows_transition"."workflow_id", "wcm_workflows_transition"."name"
ORDER BY "wcm_workflows_transition"."name" ASC;

Я не могу использовать aggregate, потому что хочу использовать набор запросов в подзапросе.
Вотмодели (упрощенно)

class Workflow:
    name = models.CharField(_(u'Name'), max_length=100, unique=True, db_index=True)


class Transition(models.Model):
    name = models.CharField(_(u'Name'), max_length=100, db_index=True)
    workflow = models.ForeignKey(Workflow, verbose_name=_(u'Workflow'), related_name='transitions',
            db_index=True, on_delete=models.PROTECT)

    class Meta:
        ordering = ('name', )

Теперь у меня есть два вопроса:

  1. Почему Django ORM добавляет эти поля в предложение GROUP BY?
  2. Каквыполнить ожидаемый запрос, используя ORM

Что я пробовал:

Я думал, что Django добавил в GROUP BY все поля, которые используются в аннотации, поэтому я изменилполе агрегируется, но оно не меняет сгруппированные по полям.
Затем я спросил себя, имеет ли поле name какое-либо ограничение. На самом деле оно имеет ограничение db_index=True. Таким образом, я изменил агрегированное поле на не ограниченное, но name было все еще в GROUP BY

1 Ответ

0 голосов
/ 30 октября 2019

Почему Django ORM добавляет эти поля в предложение GROUP BY?

Поскольку добавленное поле является полем ORDER BY по умолчанию.
Это можно увидеть в классе Meta в Transition модель: ordering = ('name', )

Как выполнить ожидаемый запрос с помощью ORM?

Добавить order_by() к вашему запросу, чтобы очистить все запросы по умолчанию. Это выглядит так:

Transition.objects.order_by().values("workflow__id").annotate(names=ArrayAgg("label")).values("names")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...