PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come restituire solo l'orario di lavoro dalle prenotazioni in PostgreSql?

Puoi utilizzare la funzione generate_series() per mascherare gli orari non lavorativi:

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

Lascia che ti spieghi alcune parti complicate:

  • non è necessario inserire le date di sab/dom in pyha tabella perché puoi usare date_part('dow', d) funzione. Usa pyha tavolo solo per i giorni festivi. 'dow' restituisce 0 o 6 rispettivamente per dom o sab.
  • I giorni festivi e sab/dom possono essere rappresentati come intervallo singolo (0..24). I giorni della settimana devono essere rappresentati da due intervalli (0..8) e (18..24), quindi unnest() e array[]
  • puoi specificare la data di inizio e la lunghezza nella funzione generate_series()

Sulla base del tuo aggiornamento alla domanda ho aggiunto un altro when a case :

when d::date = '2012-11-14' then array[tsrange(d, d + interval '9 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]

L'idea è di produrre intervalli diversi per la data di inizio (d::date = '2012-11-14' ):(0..9) e (18..24)