SQL-запрос для поиска по дню / месяцу / году / дню и месяцу / дню и году и т. Д. - PullRequest
0 голосов
/ 09 июня 2011

У меня есть база данных PostgreSQL с событиями. Каждое событие имеет дату или время. Общие данные хранятся в таблице events, а даты хранятся либо в events_dates (datetime поле), либо в events_intervals (starts_date, ends_date оба поля date).

Пример событий даты и времени

  • Я родился в 1930-06-09
  • Я получил водительские права в 1950-07-12
  • Рождество 1900-12-24 (1900 зарезервировано для ежегодных повторных мероприятий)

Примеры интервальных событий

  • Я буду в отпуске с 2011-06-09 по 2011-07-23

Теперь у меня есть пользователь, который захочет посмотреть эти события. Они смогут заполнить форму с полями from и to и в этих полях могут ввести полную дату, день, месяц, год, день и месяц, день и год, месяц и год в одном или обоих полях. .

Примеры запросов

  • С 3 мая по 21 декабря 2012 года будут проводиться мероприятия с 3 по 21 декабря, максимальный год которых составляет 2012 год
  • С 3 по 15 день будут искать события с 3-го по 15-е число каждого месяца и года
  • Начиная с 3-го дня будут искать события 3-го числа каждого месяца и года (то же самое, если from пусто, а to нет)
  • С 3 мая по июнь будут искать события с 3 мая по последний день июня каждого года
  • и т.д.

Какие-нибудь советы о том, как написать обслуживаемый запрос (он не обязательно должен быть быстрым)?

Некоторые вещи, о которых мы думали

  • записать все возможные from, to и комбинации день / месяц / год - не поддерживаются
  • сравнить даты в виде строк, например input: ____-06-__, где _ - подстановочный знак - мне не нужно было бы создавать все возможные комбинации, но это не работает для интервалов

1 Ответ

1 голос
/ 09 июня 2011

Вы можете написать поддерживаемые запросы, которые также являются быстрыми, используя расширение pg / temporal:

https://github.com/jeff-davis/PostgreSQL-Temporal

create index on events using gist(period(start_date, end_date));

select *
from events
where period(start_date, end_date) @> :date;

select *
from events
where period(start_date, end_date) && period(:start, :end);

Вы даже можете использовать его, чтобы запретить наложения как ограничение таблицы:

alter table events
add constraint overlap_excl
exclude using gist(period(start_date, end_date) WITH &&);

записывать все возможные комбинации из, в, и комбинации день / месяц / год - не поддерживаются

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

select *
from events
join generate_series(:start_date, :end_date, :interval) as datetime
on start_date <= datetime and datetime < end_date;

Но гораздо лучше использовать вышеупомянутый тип периода.

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