Postgres 9.2 has a range type, and I would recommend using them.
create table reservation (reservation tsrange); insert into reservation values ('[2012-11-14 09:00:00,2012-11-14 10:00:00)'), ('[2012-11-14 10:00:00,2012-11-14 11:30:00)'), ('[2012-11-14 12:00:00,2012-11-14 14:00:00)'), ('[2012-11-14 16:00:00,2012-11-14 18:30:00)'); ALTER TABLE reservation ADD EXCLUDE USING gist (reservation WITH &&);
"EXCLUDE USE gist" creates an index that prevents insertion from overwriting records. You can use the following query to find spaces (vyegorov query variant):
with gaps as ( select upper(reservation) as start, lead(lower(reservation),1,upper(reservation)) over (ORDER BY reservation) - upper(reservation) as gap from ( select * from reservation union all values ('[2012-11-14 00:00:00, 2012-11-14 08:00:00)'::tsrange), ('[2012-11-14 18:00:00, 2012-11-15 00:00:00)'::tsrange) ) as x ) select * from gaps where gap > '0'::interval;
'union all values' masks non-working hours, so you can make a reservation only from 8 a.m. to 6 p.m.
Here is the result:
start | gap ---------------------+---------- 2012-11-14 08:00:00 | 01:00:00 2012-11-14 11:30:00 | 00:30:00 2012-11-14 14:00:00 | 02:00:00
Documentation links: - http://www.postgresql.org/docs/9.2/static/rangetypes.html "Range Types" - https://wiki.postgresql.org/images/7/73/Range-types-pgopen -2012.pdf
source share