PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So validieren Sie überlappende Zeiten in Rails mit postgresql

Sie müssen das Rad in PostgreSQL nicht neu erfinden, es gibt zwei implementierte einfache Methoden, um Überlappungsprüfungen zu erreichen:

  1. SQLs OVERLAPS Betreiber :

Ganz einfach,

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

Dies ermöglicht jedoch, dass ein Bereich genau nach dem anderen liegt
(mit anderen Worten, es prüft start <=time ).

  1. Bereichstypen && (überlappt) Operator :

Das ist normalerweise auch einfach. Aber PostgreSQL hat keinen eingebauten Bereichstyp für time (allerdings gibt es tsrange , tstzrange und daterange für die anderen zeitlichen Typen).

Sie müssen diesen Bereichstyp für sich selbst erstellen:

CREATE TYPE timerange AS RANGE (subtype = time);

Aber danach können Sie die Überlappung mit

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

Vorteile von Bereichstypen:

  • Sie können selbst steuern, wie Sie mit Bereichsgrenzen umgehen möchten

    z.B. Sie könnten timerange(start_at, end_at, '[]') verwenden um sowohl den Start- als auch den Endpunkt der Bereiche einzubeziehen. Standardmäßig schließt es den Anfang ein, schließt aber den Endpunkt der Bereiche aus.

  • es kann indiziert werden, z.B. mit

    CREATE INDEX events_times_idx ON events USING GIST (timerange(start_at, end_at));
    
  • Ausschlussbeschränkungen :Dies ist im Wesentlichen dasselbe, was Sie erreichen möchten, aber es wird auf DB-Ebene durchgesetzt (wie UNIQUE oder andere Einschränkungen):

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