Можете да използвате функцията generate_series(), за да маскирате неработно време:
with gaps as (
select
upper(during) as start,
lead(lower(during),1,upper(during)) over (ORDER BY during) - upper(during) as gap
from (
select during
from reservation
union all
select
unnest(case
when pyha is not null then array[tsrange(d, d + interval '1 day')]
when date_part('dow', d) in (0, 6) then array[tsrange(d, d + interval '1 day')]
when d::date = '2012-11-14' then array[tsrange(d, d + interval '9 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]
else array[tsrange(d, d + interval '8 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]
end)
from generate_series(
'2012-11-14'::timestamp without time zone,
'2012-11-14'::timestamp without time zone + interval '2 week',
interval '1 day'
) as s(d)
left join pyha on pyha = d::date
) as x
)
select *
from gaps
where gap > '0'::interval
order by start
Нека обясня някои трудни части:
- не е нужно да вмъквате дати за сб/слънце в
pyha
таблица, защото можете да използватеdate_part('dow', d)
функция. Използвайтеpyha
маса само за официални празници. 'dow' връща 0 или 6 съответно за слънце или събота. - официалните празници и събота/слънце могат да бъдат представени като единичен интервал (0..24). Дните от седмицата трябва да бъдат представени с два интервала (0..8) и (18..24), следователно unnest() и array[]
- можете да посочите начална дата и дължина във функцията generate_series()
Въз основа на вашата актуализация на въпроса добавих друг when
към case
:
when d::date = '2012-11-14' then array[tsrange(d, d + interval '9 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]
Идеята е да се създадат различен(и) интервал(и) за начална дата (d::date = '2012-11-14'
):(0..9) и (18..24)