2014-07-02 4 views
0

У меня вопрос о дизайне базы данных.База данных для сохранения диапазона дат

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

Итак, есть два решения я пытаюсь оценить:

  1. цена магазин за каждый день. Проблема состояла бы в том, чтобы у нас было более 3000 разных отелей, поэтому в итоге таблица цен будет содержать более 10 миллионов строк.

  2. Хранить дату в течение целого года в виде массива байтов, каждый бит представляет собой 1 день. Таким образом, каждая строка для цены будет включать весь временной интервал, на который рассчитана цена. Проблема для этого заключалась бы в том, как индексировать массив байтов даты и как быстро будет поиск; и обработка трансфертной цены вы вводите в правильный формат.

Какое решение я должен использовать? Я ничего не пробовал и не знаю, как разные базы данных обрабатывают разные сценарии и как индексирование байтового массива (строки) работает для сравнения побитовой операции и т. Д. Любое другое предложение приветствуется.

+0

В случае (2), как вы убедитесь, что для данной даты и места, вы не имеете много цены ? Вам нужно сделать двоичный 'и' на всех существующих строках, чтобы избежать совпадений. – didierc

+1

Если с 1 по 7 июля номер стоит 100 фунтов стерлингов, а 8-14 июля номер стоит 150 фунтов стерлингов, но я скачу, скажем, 4-10 июля, какой тариф будет взиматься? –

+0

, вы будете платить за каждый день – user2412555

ответ

2

Поскольку вы также помечены это с PostgreSQL, новый тип интервала данные введены в 9.2, кажется, как хороший (и эффективно) подходят здесь:

Упрощенный пример будет выглядеть следующим образом:

create table room_price 
(
    room_id  integer  not null, 
    hotel_id  integer  not null, 
    price   numeric(16,4) not null, 
    valid_during daterange not null 
); 

Тогда вы можете вставить что-то вроде этого:

insert into room_price 
    (room_id, hotel_id, price, valid_during) 
values 
    (1, 1, 100.0, '[2014-07-01,2014-07-01]'), 
    (1, 1, 90.0, '[2014-07-02,2014-07-12]'); 

[...] обозначения определяет интервал, который включает в себя обе даты ([..) будет определять интервал, исключающий левый край).

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

select * 
from room_price 
where room_id = 1 
    and valid_during @> date '2014-07-04; 

бы вернуть цену с 90,0

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

alter table room_price 
    add constraint check_price_range 
    exclude using gist (room_id with =, valid_during with &&) 

с учетом указанных выше ограничений Postgres бы отклонять следующую вставку:

insert into room_price 
    (room_id, hotel_id, price, valid_during) 
values 
    (1, 90.0, '[2014-07-03,2014-07-04]'); 

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

+0

Проблема с этим дизайном будет заключаться в том, как сопоставить временной интервал, который соответствует более чем нескольким строкам, и как, конечно, изменить добавленную новую цену, которая перекрывается с более старым временным интервалом цены. – user2412555

+0

* Тип данных integer не имеет класса оператора по умолчанию для метода доступа «gist» * по умолчанию: вы можете использовать модуль 'btree_gist' или определить ограничение исключения с помощью' exclude using gist (int4range (room_id, room_id, '[]') с &&, valid_during с &&) ' – pozs

+0

@ user2412555 вот пример, как выполнить запрос через несколько диапазонов (с разными ценами): http://sqlfiddle.com/#!15/4b69f/8 - зачем вы хотите добавить новые цены, которые совпадают с более старыми ценами? – pozs

1

PostgreSQL имеет пару функций, специально предназначенных для такого рода вещей: типы диапазонов и ограничения исключения.

Храните цены со сроком действия как диапазон или набор диапазонов. Затем определите ограничения исключения, чтобы убедиться, что нет совпадений, когда две цены действительны для данного места/времени.

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

Чтобы узнать больше:

Смежные вопросы