django通过cocece从同一模型中获取最大长度值

发布于 2025-01-25 18:14:53 字数 1086 浏览 1 评论 0原文

我正在尝试使用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
class Contact(models.Model):
    first_name = models.CharField(max_length=250)
    last_name = models.CharField(max_length=250, null=True, blank=True)
    middle_name = models.CharField(max_length=250, null=True, blank=True)

DB:Postgres
Django版本:3.12

I'm trying to write the following raw query with the ORM. I'm not sure is it possible or not.

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

The expected result is like the following, if middle_name is null, get the middle name from another record that has the same first_name and last_name.

id| first_name | middle_name | expected | last_name
1 | ahmet      |   <NULL>    |  burak   |   ozyurt
2 | ahmet      |   burak     |  burak   |   ozyurt
class Contact(models.Model):
    first_name = models.CharField(max_length=250)
    last_name = models.CharField(max_length=250, null=True, blank=True)
    middle_name = models.CharField(max_length=250, null=True, blank=True)

DB: Postgres
Django Version: 3.12

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

jJeQQOZ5 2025-02-01 18:14:53

通过使用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")
)

说明

  1. models.OuterRef用于从子查询的父级查询中引用该字段。
  2. - order_by中的前缀(“ - Midder_name_len”)用于降序顺序
  3. .values(“ Midder_name”)用于仅选择midder_name值。
  4. 切片[:1]是为了将子查询的结果限制为一个。

提示

  • 您可以使用result.query检查ORM将为您生成的查询。

By using the django ORM, you can perform the same query by using the following code

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

Explanations

  1. models.OuterRef is used for referring to the field from the parent query of a subquery.
  2. - prefix in the order_by("-middle_name_len") is for descending order
  3. .values("middle_name") is for selecting only middle_name values.
  4. the slicing [:1] is for limiting the result from the subquery to be one.

Tips

  • You can use result.query to inspect what query the ORM will generate for you.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文