sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo validar tiempos superpuestos en Rails con postgresql

No necesita reinventar la rueda en PostgreSQL, hay dos métodos simples implementados para lograr controles de superposición:

  1. SQL OVERLAPS operador :

Bastante simple,

where("(start_at, end_at) OVERLAPS (?, ?)", range.first, range.last)

Sin embargo, esto permite que un rango esté exactamente después del otro
(en otras palabras, verifica start <=time ).

  1. Tipos de rango' && operador (superpuestos) :

Esto también es simple, por lo general. Pero PostgreSQL no tiene un tipo de rango incorporado para time (sin embargo, hay tsrange , tstzrange y daterange para los otros tipos temporales).

Necesitas crear este tipo de rango por ti mismo:

CREATE TYPE timerange AS RANGE (subtype = time);

Pero después de esto, puede verificar la superposición con

where("timerange(start_at, end_at) && timerange(?, ?)", range.first, range.last)

Ventajas de los tipos de rango:

  • puedes controlarte a ti mismo, ¿cómo quieres manejar los límites del rango?

    p.ej. podrías usar timerange(start_at, end_at, '[]') para incluir tanto el inicio como el punto final de los rangos. Por defecto incluye el inicio, pero excluye el punto final de los rangos.

  • se puede indexar, p.ej. con

    CREATE INDEX events_times_idx ON events USING GIST (timerange(start_at, end_at));
    
  • Restricciones de exclusión :esto es esencialmente lo mismo, lo que desea lograr, pero se aplicará a nivel de base de datos (como, UNIQUE o cualquier otra restricción):

    ALTER TABLE events
      ADD CONSTRAINT events_exclude_overlapping
      EXCLUDE USING GIST (timerange(start_at, end_at) WITH &&);