Ограничение уникальности с диапазоном дат

15

Рассмотрим pricesтаблицу с этими столбцами:

id         integer primary key
product_id integer -- foreign key
start_date date not null
end_date   date not null
quantity   integer
price      numeric

Я бы хотел, чтобы база данных применяла правило, согласно которому продукт может иметь только одну цену на определенное количество в диапазоне дат (через where <date> BETWEEN start_date AND end_date).

Возможно ли такое ограничение на основе диапазона?

колос
источник

Ответы:

23

Да, вы можете использовать EXCLUDEограничение, которое является обобщением UNIQUEограничений:

ALTER TABLE prices 
  ADD CONSTRAINT unique_price_per_product_quantity_daterange
    EXCLUDE  USING gist
    ( product_id WITH =, 
      quantity WITH =, 
      daterange(start_date, end_date, '[]') WITH &&   -- this is the crucial
    );

Ограничение можно интерпретировать как высказывание:

Не допускайте двух строк с одинаковыми product_id, одинаковыми quantityи перекрывающимися &&диапазонами дат.

Предназначен '[]'для требуемого диапазона дат «все включено» (по умолчанию [)для типов диапазона).

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

CREATE EXTENSION btree_gist;
ypercubeᵀᴹ
источник
Это круто. Я не думаю , что daterangeэто точно такой же , так как это эксклюзивная нижняя граница, но это легко исправить. Должен ли я действительно переносить свои данные для использования daterangeтипа столбца (можно ли сделать это отдельным вопросом, если так лучше) или это целесообразно с двумя столбцами?
шип
По умолчанию включительно нижняя граница и исключительная верхняя граница, если я хорошо помню. Я буду редактировать для все включено. Я обычно предпочитаю значение по умолчанию, так как оно часто встречается в гостиничных приложениях. (Я вхожу в отель 2-го, я
выхожу
Я мог бы на самом деле узнать, какие именно ... только что узнал о типах диапазонов сегодня, и я читаю документы!
шип
Я не уверен, что предпочтительнее, 2 столбца или один с датой. Вы можете задать отдельный вопрос. Вероятно, это будет зависеть от того, какое вы хотите использовать, запросов, простоты использования (и потребностей в индексировании). Если есть отдельные столбцы, например, было бы проще иметь индекс (product_id, start_date). С диапазоном дат это должно быть индексом на(product_id, lower(range_column))
ypercubeᵀᴹ