Du behøver ikke at genopfinde hjulet i PostgreSQL, der er to implementerede enkle metoder til at opnå overlapningstjek:
- SQL's
OVERLAPS
operatør :
Simpelt nok,
where("(start_at, end_at) OVERLAPS (?, ?)", range.first, range.last)
Dette gør det dog muligt for det ene område at være nøjagtigt efter det andet
(med andre ord kontrollerer det start <=tid
Dette er normalt også simpelt. Men PostgreSQL har ikke en indbygget områdetype for time
(der er dog tsrange
, tstzrange
og daterange
for de andre tidsmæssige typer).
Du skal oprette denne områdetype til dig selv:
CREATE TYPE timerange AS RANGE (subtype = time);
Men efter dette kan du kontrollere overlapning med
where("timerange(start_at, end_at) && timerange(?, ?)", range.first, range.last)
Fordele ved rækketyper:
-
du kan styre dig selv, hvordan vil du håndtere rækkeviddegrænser
f.eks. du kan bruge
timerange(start_at, end_at, '[]')
for at inkludere både start- og slutpunktet for områderne. Som standard inkluderer den starten, men udelukker slutpunktet for områderne. -
det kan indekseres, f.eks. med
CREATE INDEX events_times_idx ON events USING GIST (timerange(start_at, end_at));
-
Ekskluderingsbegrænsninger :dette er stort set det samme, hvad du ønsker at opnå, men det vil blive håndhævet på DB-niveau (som,
UNIQUE
eller andre begrænsninger):ALTER TABLE events ADD CONSTRAINT events_exclude_overlapping EXCLUDE USING GIST (timerange(start_at, end_at) WITH &&);