【问题标题】:Raw SQL in order by in django model query在 Django 模型查询中按顺序排列的原始 SQL
【发布时间】:2021-10-01 20:22:54
【问题描述】:

我有一个这样的简单查询(我希望先出现 1 BHK,然后是 2BHK,然后是其他任何东西

select *
from service_options
order by case space when '1BHK' then 0 when '2BHK' then 1 else 2 end,
         space

在 Django 中,怎么做?我有一个模型名为ServiceOption

我试过了,但没有运气。

ServiceOption.objects.order_by(RawSQL("case space when '1BHK' then 0 when '2BHK' then 1 else 2 end,space"), ()).all()

我不想使用类似的东西执行原始查询

ServiceOption.objects.raw("raw query here")

Laravel 中,这样的事情可以很容易地像这样实现

Model::query()->orderByRaw('raw order by query here')->get();

我们将不胜感激。提前谢谢你。

【问题讨论】:

    标签: django django-models django-rest-framework django-views django-templates


    【解决方案1】:

    您可以使用.annotate(…) [Django-doc],然后使用.order_by(…) [Django-doc]

    from django.db.models import Case, IntegerField, Value, When
    
    ServiceOption.objects.annotate(
        sp=Case(
            When(space='1BHK', then=Value(0)),
            When(space='2BHK', then=Value(1)),
            default=Value(2),
            output_field=IntegerField()
        )
    ).order_by('sp', 'space')

    原始查询会到这里

    SELECT *, CASE WHEN "service_options"."space" = 1BHK THEN 0 WHEN "service_options"."space" = 2BHK THEN 1 ELSE 2 END AS "sp" FROM "service_options" ORDER BY "sp" ASC, "service_options"."space" ASC
    

    由于,您可以使用.alias(…) [Django-doc] 来防止将其计算为列和ORDER BY 子句:

    from django.db.models import Case, IntegerField, Value, When
    
    ServiceOption.objects.alias(
        sp=Case(
            When(space='1BHK', then=Value(0)),
            When(space='2BHK', then=Value(1)),
            default=Value(2),
            output_field=IntegerField()
        )
    ).order_by('sp', 'space')

    原始查询会到这里

    SELECT * FROM "service_options" ORDER BY CASE WHEN ("service_options"."space" = 1BHK) THEN 0 WHEN ("service_options"."space" = 2BHK) THEN 1 ELSE 2 END ASC, "service_options"."space" ASC
    

    【讨论】:

    • 您好,感谢您的解决方案。但是,有没有办法只为 order by 执行原始查询?在 laravel 中,我可以使用 $query->orderByRaw('raw order by query here') 之类的方法轻松完成。
    • 为您的答案执行的实际查询将转换为 select *, case space when '1BHK' then 0 when '2BHK' then 1 else 2 end as sp from service_options order by sp, space 但是,这与我在问题中建议的原始查询完全不同。
    • @KoushikDas: 不,如果您使用.annotate 执行此操作,那么它将在SELECTORDER BY 子句中使用sp,如果您使用.alias(...)它只会在必要的地方使用ORDER BY 中的CASE ...
    猜你喜欢
    • 1970-01-01
    • 2013-04-17
    • 2015-11-21
    • 2012-03-16
    • 1970-01-01
    • 2017-11-19
    • 1970-01-01
    • 2017-05-04
    • 2022-01-11
    相关资源
    最近更新 更多