Django получает значение максимальной длины из одной модели с помощью Coalesce
Я пытаюсь написать следующий необработанный запрос с помощью ORM. Я не уверен, возможно ли это или нет.
select first_name,
middle_name,
COALESCE(middle_name, (
select middle_name
from contacts c2
where c2.first_name = c1.first_name
and c2.last_name = c1.last_name
and c2.middle_name is not null
order by length(c2.middle_name) desc
limit 1
)
) expected,
last_name
from contacts c1
Ожидаемый результат будет следующим, если middle_name равно null, получите среднее имя из другой записи, которая имеет те же first_name и last_name.
id| first_name | middle_name | expected | last_name
1 | ahmet | <NULL> | burak | ozyurt
2 | ahmet | burak | burak | ozyurt
DB: Postgres
Django Версия: 3.12
Используя django ORM, вы можете выполнить тот же запрос с помощью следующего кода
from django.db import models
from django.db.models.functions import Coalesce, Length
matched_middle_name_queryset = Contact.objects.filter(
first_name=models.OuterRef("first_name"),
last_name=models.OuterRef("last_name"),
middle_name__isnull=False,
).annotate(
middle_name_len=Length("middle_name")
).order_by("-middle_name_len").values("middle_name")[:1]
result = Contact.objects.annotate(
matched_middle_name=models.Subquery(matched_middle_name_queryset)
expected=Coalesce(
models.F("middle_name")
models.F("matched_middle_name"),
).values("id", "first_name", "middle_name", "expected", "last_name")
)
Пояснения
models.OuterRefиспользуется для ссылки на поле из родительского запроса подзапроса.-префикс вorder_by("-middle_name_len")используется для нисходящего порядка .
.values("middle_name")предназначен для выбора толькоmiddle_nameзначений.- нарезка
[:1]предназначена для ограничения результата подзапроса одним значением.
Советы
- Вы можете использовать
result.query, чтобы проверить, какой запрос ORM будет генерировать для вас.