Restricción de unicidad con rango de fechas


15

Considere una pricestabla con estas columnas:

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

Me gustaría que la base de datos haga cumplir la regla de que un producto solo puede tener un precio en una cantidad específica en un rango de fechas (vía where <date> BETWEEN start_date AND end_date).

¿Es factible este tipo de restricción basada en el rango?

Respuestas:


23

Sí, puede usar una EXCLUDErestricción, que es una generalización de UNIQUErestricciones:

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
    );

La restricción puede interpretarse como diciendo:

No permita dos filas que tengan rangos de fechas iguales product_id, iguales quantityy superpuestos ( &&).

El '[]'es para el rango de fechas todo incluido deseado (el valor predeterminado es [)para los tipos de rango).

Consulte la documentación sobre restricciones en los tipos de rango . Probablemente también necesite agregar la extensión ejecutando (una vez, para cada base de datos donde quiera que esté instalada):

CREATE EXTENSION btree_gist;

Esto es asombroso No creo que daterangesea exactamente lo mismo ya que es un límite inferior exclusivo, pero eso es fácil de arreglar. ¿Realmente debería migrar mis datos para usar un daterangetipo de columna (puede hacer que sea una pregunta por separado si eso es mejor) o es razonable esto de dos columnas?
pico

El valor predeterminado en límite inferior inclusivo y límite superior exclusivo, si mal no recuerdo. Lo editaré para todo incluido. Por lo general, prefiero el valor predeterminado, ya que es común en aplicaciones tipo hotel. (Entro en el hotel el 2, me bajo en el 8, me quedé 6 días. El siguiente ocupante puede entrar en el 8)
ypercubeᵀᴹ

De hecho, podría cambiarme cuál es cuál ... ¡acabo de enterarme de los tipos de rango hoy y estoy leyendo los documentos!
pico

No estoy seguro de lo que es preferible, 2 columnas o una con rango de fechas. Puedes hacer una pregunta por separado. Probablemente dependerá del uso que desee, consultas, facilidad de uso (y necesidades de índice). Si hay columnas separadas, sería más fácil, por ejemplo, tener un índice activado (product_id, start_date). Con un rango de fechas, eso tendría que ser un índice en(product_id, lower(range_column))
ypercubeᵀᴹ
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.