Ответ 1
SELECT *
FROM mytable
WHERE (start_date, end_date) OVERLAPS ('2012-01-01'::DATE, '2012-04-12'::DATE);
Функции Datetime - это соответствующий раздел в документах.
У меня есть следующая таблица:
+-----------+-----------+------------+----------+
| id | user_id | start_date | end_date |
| (integer) | (integer) | (date) | (date) |
+-----------+-----------+------------+----------+
Поля start_date
и end_date
содержат значения даты, такие как YYYY-MM-DD
.
Запись из этой таблицы может выглядеть так: (1, 120, 2012-04-09, 2012-04-13)
.
Мне нужно написать запрос, который может получить все результаты, соответствующие определенному периоду.
Проблема в том, что если я хочу получить результаты от 2012-01-01
до 2012-04-12
, я получаю 0 результатов, даже если есть запись с start_date = "2012-04-09"
и end_date = "2012-04-13"
.
SELECT *
FROM mytable
WHERE (start_date, end_date) OVERLAPS ('2012-01-01'::DATE, '2012-04-12'::DATE);
Функции Datetime - это соответствующий раздел в документах.
Предполагая, что вам нужны все " перекрывающиеся" периоды времени, т.е. все, имеющие хотя бы один день вместе.
Постарайтесь представить периоды времени на прямой линии времени и перемещать их перед глазами, и вы увидите необходимые условия.
SELECT *
FROM tbl
WHERE start_date <= '2012-04-12'::date
AND end_date >= '2012-01-01'::date;
Для меня это иногда быстрее, чем OVERLAPS
- это другой хороший способ сделать это (как @Marco уже предоставлен).
Обратите внимание на тонкую разницу (на документацию):
OVERLAPS
автоматически принимает более раннее значение пары как Начало. Каждый период времени считается полуоткрытым интервалstart <= time < end
, если только начало и конец не равны, случай представляет собой одноразовый момент. Это означает, например, что два временных периода с общей общей точкой не перекрываются.
Смелый акцент мой.
Для больших таблиц правильный индекс может помочь производительности (много).
CREATE INDEX tbl_date_inverse_idx ON tbl(start_date, end_date DESC);
Возможно, с другим (ведущим) столбцом индекса, если у вас есть дополнительные выборочные условия.
Обратите внимание на обратный порядок двух столбцов. Подробное объяснение:
имел тот же самый вопрос и ответил так, если бы это могло помочь.
select *
from table
where start_date between '2012-01-01' and '2012-04-13'
or end_date between '2012-01-01' and '2012-04-13'
Чтобы запрос работал в любых настройках локали, подумайте форматирование даты самостоятельно:
SELECT *
FROM testbed
WHERE start_date >= to_date('2012-01-01','YYYY-MM-DD')
AND end_date <= to_date('2012-04-13','YYYY-MM-DD');
Глядя на даты, для которых он не работает - те, где день меньше или равен 12 - Мне интересно, обрабатывает ли он даты в формате YYYY-DD-MM?
Вы должны использовать метод выборки даты:
SELECT * FROM testbed WHERE start_date ::date >= to_date('2012-09-08' ,'YYYY-MM-DD') and date::date <= to_date('2012-10-09' ,'YYYY-MM-DD')
Без обид, но для проверки производительности sql я выполнил часть вышеупомянутого решения pgsql.
Позвольте мне поделиться с вами Статистика Топ-3 решений, с которыми я сталкиваюсь.
1) Взято: 1,58 MS Avg
2) Взял: 2.87 MS Avg
3) Взял: 3,95 MS Avg
Теперь попробуйте следующее:
SELECT * FROM table WHERE DATE_TRUNC('day', date ) >= Start Date AND DATE_TRUNC('day', date ) <= End Date
Теперь это решение получило: 1,61 Сред.
И лучшее решение - это первое, что предлагается marco-mariani
SELECT *
FROM ecs_table
WHERE (start_date, end_date) OVERLAPS ('2012-01-01'::DATE, '2012-04-12'::DATE + interval '1');