Django ORM使用Case和When條件表示式
阿新 • • 發佈:2020-09-03
問題
有這麼一個需求,需要根據訂單的建立時間和更新時間排序,要按照最後的操作時間進行排序。
比如,在26分建立了一個訂單a,在27分建立了一個訂單b,然後在28分修改訂單a,又在29分建立了訂單c,那麼此時訂單的排序結果,應該是c,a,b。
表中資料(時間是示例,實際是datetime.datetime型別):
ID | 訂單號 | 建立時間 | 更新時間 |
---|---|---|---|
1 | a | 26 | 28 |
2 | b | 27 | |
3 | c | 29 |
方案
一開始的想法是根據更新時間排序,然後更新時間為空的,按照建立時間排序。但是這種方式對於沒有更新時間的資料,篩選出來會出現排序混亂的問題。
後來想到可以將兩個欄位合成一個欄位,這樣就可以對這個欄位排序了,但是也有問題,合成一個欄位,會出現資料重複,而且也不好篩選和過濾。
在網上搜了搜,看到可以使用SQL的條件表示式,case,when,then。
實現
SQL使用條件表示式,可以判斷update_time是否為空,如果有值,則使用自己的值,如果沒有值則使用create_time,並且可以對結果使用別名,然後根據這個別名來進行排序。這樣排序的時候就會同時根據更新時間和建立時間來排序。
程式碼示例
完整程式碼示例:
from django.db.models import Case, DateTimeField, F, When # 查詢所有的資料,只要queryset是Django查詢集即可 queryset = Order.objects.all() # queryset.annotate( op_time=Case( When(update_time=F("update_time"), then=F("update_time"),), default=F("create_time"), output_field=DateTimeField(), ), ).order_by("-op_time")
完整的SQL示例:
SELECT
id,
create_time,
update_time,
(
CASE update_time
WHEN update_time THEN
update_time
ELSE
create_time
END) AS t
FROM
courtesy_car_order
ORDER BY
t DESC