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
posted @ 2020-09-03 17:30  zzhaoleiの博客  阅读(2021)  评论(0编辑  收藏  举报