Я хочу сгенерировать следующий запрос:
select id, (select count(*) from B where B.x = A.x) as c from A
Что должно быть достаточно просто с выражением Подзапрос . За исключением того, что к моему запросу на счет добавляется оператор group by
, от которого я не могу избавиться:
from django.contrib.contenttypes.models import ContentType
str(ContentType.objects.annotate(c=F('id')).values('c').query)
# completely fine query with annotated field
'SELECT "django_content_type"."id" AS "c" FROM "django_content_type"'
str(ContentType.objects.annotate(c=Count('*')).values('c').query)
# gets group by for every single field out of nowhere
'SELECT COUNT(*) AS "c" FROM "django_content_type" GROUP BY "django_content_type"."id", "django_content_type"."app_label", "django_content_type"."model"'
, что делает результат [{'c': 1}, {'c': 1}, {'c': 1}, {'c': 1},...]
вместо [{c:20}]
. Но подзапросы должны иметь только одну строку результатов, чтобы их можно было использовать.
Поскольку запрос предполагается использовать в подзапросе, я не могу использовать .count()
или .aggregate()
, так как они оцениваются мгновенно и жалуются об использовании OuterRef
выражения.
Пример с подзапросом:
str(ContentType.objects.annotate(fields=Subquery(
Field.objects.filter(model_id=OuterRef('pk')).annotate(c=Count('*')).values('c')
)).query)
Генерирует
SELECT "django_content_type"."id",
"django_content_type"."app_label",
"django_content_type"."model",
(SELECT COUNT(*) AS "c"
FROM "meta_field" U0
WHERE U0."model_id" = ("django_content_type"."id")
GROUP BY U0."id", U0."model_id", U0."module", U0."name", U0."label", U0."widget", U0."visible", U0."readonly",
U0."desc", U0."type", U0."type_model_id", U0."type_meta_id", U0."is_type_meta", U0."multi",
U0."translatable", U0."conditions") AS "fields"
FROM "django_content_type"
Ожидаемый запрос:
SELECT "django_content_type"."id",
"django_content_type"."app_label",
"django_content_type"."model",
(SELECT COUNT(*) AS "c"
FROM "meta_field" U0
WHERE U0."model_id" = ("django_content_type"."id")) AS "fields"
FROM "django_content_type"
Обновление: (чтобы добавить модели из реального приложения, запрошенного в комментариях):
class Translation(models.Model):
field = models.ForeignKey(MetaField, models.CASCADE)
ref_id = models.IntegerField()
# ... other fields
class Choice(models.Model):
meta = models.ForeignKey(MetaField, on_delete=models.PROTECT)
# ... other fields
Мне нужен запрос, чтобы получить количество переводов, доступных для каждого выбора, где Translation.field_id
относится к Choice.meta_id
и Translation.ref_id
относится на Choice.id
.
Причина отсутствия внешних ключей заключается в том, что не все мета-поля являются полями выбора (например, текстовые поля также могут иметь переводы). Я мог бы создать отдельную таблицу для каждой переводимой сущности, но эта настройка должна быть простой в использовании с подзапросом count, в котором нет оператора group by
.