Проблема оператора SQL OVERLAPS, как от него избавиться - PullRequest
5 голосов
/ 07 марта 2011

Я ожидаю, что этот период дат с «2011-01-28» до «2011-02-01» ПЕРЕКРЫВАЕТ период с «2011-02-01» на «2011-02-01» (это тот же день, что и здесь), но это не так!

PostgreSQL, ожидающий совпадения с точной конечной точкой, НЕ совпадает ... как избавиться от этого? Я хотел бы, чтобы это рассматривало вышеупомянутый сценарий как наложение.

SELECT (DATE '2011-01-28', DATE '2011-02-01') OVERLAPS
       (DATE '2011-02-01', DATE '2011-02-01');

возвращает false, в то время как я ожидаю, что он вернет true.

Ответы [ 4 ]

12 голосов
/ 08 марта 2011

Вы ожидаете, что ошиблись. Из тонкой инструкции :

Каждый период времени считается представляющим полуоткрытый интервал начало <= время <конец </em>, если только начало и конец не равны; представляет тот единственный момент времени. Это означает, например, что два периода времени с общей конечной точкой не перекрываются.

Итак, если вам нужен закрытый интервал, start <= time <= end </em>, то вы можете либо явно выполнить проверку конечной точки, как рекомендует Catcall, либо добавить один день к верхней границе :

SELECT (DATE '2011-01-28', DATE '2011-02-01' + 1) OVERLAPS
       (DATE '2011-02-01', DATE '2011-02-01'    )

Но будьте осторожны, чтобы расположить конечные точки в правильном порядке:

Когда указана пара значений, сначала можно записать начало или конец; OVERLAPS автоматически принимает более раннее значение пары в качестве начала.

7 голосов
/ 07 марта 2011

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

Предполагая

  • (S1, E1) - даты начала и окончания. первого диапазона,
  • (S2, E2) - даты начала и окончания. второго диапазона,
  • Ни один из S1, E1, S2 или E2 не равен NULL,

тогда это должно вернуть строку, когда диапазоны либо перекрываются, либо примыкают друг к другу.

select S1, E1, S2, E2
from [some table name]
where (S1, E1) overlaps (S2, E2)
   or (E1 = S2)   -- first range ends on the start date of the second
   or (E2 = S1)   -- second range ends on the start date of the first
3 голосов
/ 07 марта 2011

Обходное решение, т. Е. Оно может иметь или не иметь смысла для вашего случая - преобразовать даты в отметки времени:

SELECT (TIMESTAMP '2011-01-28 00:00:00', TIMESTAMP '2011-02-01  23:59:59') OVERLAPS (TIMESTAMP '2011-02-01 00:00:00', TIMESTAMP '2011-02-01 23:59:59');

Технически достаточно преобразовать только конечную точку первого периода, по крайней мере, для приведенного вами примера.

0 голосов
/ 26 марта 2013

Почему бы не использовать классический запрос:

select (date '2013-01-01' between date '2012-12-01' and date '2013-01-01') or
       (date '2013-03-01' between date '2012-12-01' and date '2013-01-01');

В псевдокоде:

select (date 'START1' between date 'START2' and date 'END2') or
       (date 'END1' between date 'START2' and date 'END2');

Результат будет таким же, хотя порядок будет изменен:

select (date 'START2' between date 'START1' and date 'END1') or
       (date 'END2' between date 'START1' and date 'END1');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...