1. 程式人生 > 實用技巧 >Django ORM使用Case和When條件表示式

Django ORM使用Case和When條件表示式

問題

有這麼一個需求,需要根據訂單的建立時間和更新時間排序,要按照最後的操作時間進行排序。

比如,在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