Функция перекрытия Pgsql в Django - PullRequest
0 голосов
/ 17 октября 2018

Я работаю над проектом, в котором мне нужно извлечь дату из таблицы, основанной на начальной и конечной дате.Вот запрос

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 голосов
/ 17 октября 2018

Два диапазона [a 1 , b 1 ) и [a 2 , b 2 ) делать не перекрываться, если a 1 ≥b 2 или b 1 ≤a 2 .Мы можем отрицать это выражение, чтобы знать, когда два интервала перекрываются: a 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 соответственно.

Таким образом, мы можем сделать запрос, например:

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 в PostgreSQL немного сложнее, поскольку она автоматически меняет местамивремя, когда end_date больше start_date, поэтому нам, возможно, придется использовать .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, а если не поменять местами, то не потому чтов противном случае метод потерпит неудачу, но поскольку это «точные» спецификации довольно сложной функции OVERLAP).

0 голосов
/ 17 октября 2018
YourModel.objects.filter(start_date__gte='2018-09-15 03:00:00',end_date__lte='2018-09-15 03:30:00')

это должно делать то, что вы ищете.Просто замените название вашей модели на предоставленный манекен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...