Django中的pgsql重叠函数

时间:2018-10-17 13:18:25

标签: django postgresql

我正在研究一个项目,该项目需要根据开始日期和结束日期从表中提取日期。这是查询

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查询。

2 个答案:

答案 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_dateend_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')

这应该做您想要的。只需用提供的假人替换您的型号名称即可。