我正在研究一个项目,该项目需要根据开始日期和结束日期从表中提取日期。这是查询
SELECT * FROM billing_lines WHERE (start_date, end_date) OVERLAPS ('2018-09-15 03:00:00', '2018-09-15 03:30:00');
我知道我可以使用raw()
来执行上述查询。但是我的问题是,如何将其转换为Django ORM查询。
答案 0 :(得分:2)
两个范围 [a 1 ,b 1 )和 [a 2 ,b < sub> 2 )如果 a 1 ≥b 2 不重叠,或 b 1 ≤a 2 。我们可以取反此表达式,以知道两个间隔何时重叠: a 1 2 和 b 1 > a 2 。
这里start_date
和end_date
分别是 a 1 和 b 1 ,而您写的'2018-09-15 03:00:00'
和'2018-09-15 03:30:00'
的两个值就是 a 2 和 b 2 < / em>。
因此,我们可以进行如下查询:
begin='2018-09-15 03:00:00'
end='2018-09-15 03:30:00'
Lines.objects.filter(
start_date__lt=end
end_date__gt=begin
)
因此,这不会不检查(begin, end)
中的(start_date, end_date)
是否“包含”,它检查是否存在至少一个元素是两个范围的成员
现在OVERLAP
function in PostgreSQL有点复杂,因为它会自动交换时间,以防end_date
大于start_date
,因此我们可能需要使用{{1} }:
.annotate(..)
这仍然不完全相同,因为如果from django.db.models import F
from django.db.models.functions import Greatest, Least
begin='2018-09-15 03:00:00'
end='2018-09-15 03:30:00'
Lines.objects.annotate(
d0=Least(F('start_date'), F('end_date')),
d1=Greatest(F('start_date'), F('end_date')),
).filter(
d0__lt=end
d1__gt=begin
)
和d0
相同,则范围为“包含”,因此我们也应考虑这种情况:
d1
它还需要“准备” Lines.objects.annotate(
d0=Least(F('start_date'), F('end_date')),
d1=Greatest(F('start_date'), F('end_date')),
).filter(
Q(d0__lt=end, d1__gt=begin) |
Q(d0=F('d1'), d0__gte=begin, d0__lt=end)
)
和begin
(您应确保end
,如果不交换它们,不是因为否则该方法将失败,而是因为这些是相当复杂的begin <= end
函数的“精确”规范。)
答案 1 :(得分:1)
YourModel.objects.filter(start_date__gte='2018-09-15 03:00:00',end_date__lte='2018-09-15 03:30:00')
这应该做您想要的。只需用提供的假人替换您的型号名称即可。