Bạn có thể sử dụng hàm create_series () để ẩn đi những giờ không phải làm việc:
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
Hãy để tôi giải thích một số phần phức tạp:
- bạn không phải chèn ngày cho sat / sun vào
pyha
vì bạn có thể sử dụngdate_part('dow', d)
hàm số. Sử dụngpyha
bảng chỉ dành cho ngày lễ. 'dow' trả về 0 hoặc 6 cho CN hoặc Sat tương ứng. - các ngày nghỉ lễ và sat / sun có thể được biểu thị dưới dạng một khoảng thời gian duy nhất (0..24). Các ngày trong tuần phải được biểu thị bằng hai khoảng (0..8) và (18..24) do đó unnest () và array []
- bạn có thể chỉ định ngày và độ dài bắt đầu trong hàm create_series ()
Dựa trên cập nhật của bạn cho câu hỏi, tôi đã thêm một when
khác thành case
:
when d::date = '2012-11-14' then array[tsrange(d, d + interval '9 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]
Ý tưởng là tạo (các) khoảng thời gian khác nhau cho ngày bắt đầu (d::date = '2012-11-14'
):(0..9) và (18..24)