Du behöver inte uppfinna hjulet på nytt i PostgreSQL, det finns två implementerade enkla metoder för att uppnå överlappningskontroller:
- SQL:s
OVERLAPS
operatör :
Enkelt nog,
where("(start_at, end_at) OVERLAPS (?, ?)", range.first, range.last)
Detta gör det dock möjligt för ett intervall att ligga exakt efter det andra
(med andra ord kontrollerar det start <=tid
Detta är också enkelt, vanligtvis. Men PostgreSQL har ingen inbyggd intervalltyp för time
(men det finns tsrange
, tstzrange
och daterange
för de andra tidstyperna).
Du måste skapa den här intervalltypen för dig själv:
CREATE TYPE timerange AS RANGE (subtype = time);
Men efter detta kan du kontrollera överlappning med
where("timerange(start_at, end_at) && timerange(?, ?)", range.first, range.last)
Fördelar med intervalltyper:
-
du kan kontrollera dig själv, hur vill du hantera räckviddsgränser
t.ex. du kan använda
timerange(start_at, end_at, '[]')
för att inkludera både start- och slutpunkten för intervallen. Som standard inkluderar den starten, men exkluderar slutpunkten för intervallen. -
den kan indexeras, t.ex. med
CREATE INDEX events_times_idx ON events USING GIST (timerange(start_at, end_at));
-
Uteslutningsbegränsningar :detta är i huvudsak detsamma, vad du vill uppnå, men det kommer att tillämpas på DB-nivå (som,
UNIQUE
eller andra begränsningar):ALTER TABLE events ADD CONSTRAINT events_exclude_overlapping EXCLUDE USING GIST (timerange(start_at, end_at) WITH &&);