PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Diferença horária dentro do horário comercial


Sugiro gerar todos os intervalos de horário comercial entre created_at e current_timestamp e somando-os. Embora esteja longe de ser a solução ideal em termos de desempenho, acho que é a abordagem mais direta. Uso timestamp com intervalo de fuso horário tstzrange com interseção operador (*) .
SELECT id,
  created_at,
  SUM(upper(business_range) - lower(business_range) ) business_hours
FROM (
  SELECT id, 
    created_at,
    tstzrange(date_in_range + '09:00'::time with time zone, date_in_range + '17:00'::time with time zone) 
      * tstzrange(created_at, current_timestamp) as business_range
  FROM (
    SELECT id,
      created_at,
      created_at::date + generate_series(0, current_timestamp::date - created_at::date) as date_in_range 
    FROM times
  ) dates_in_range
  WHERE date_part('dow', date_in_range) in (1,2,3,4,5)
) business_hour_ranges
GROUP BY
  id,
  created_at

Veja a configuração e o exemplo em db<>fiddle

Palavra de cautela


Embora a implementação tenha sido feita para ser fácil de entender e depurar, ela pode resultar em desempenho ruim - especialmente se usada com datas created_at muito antigas. Se esse for o caso em seu sistema, talvez seja melhor escrever uma função que verifique o dia da semana do created_at e current_date, encontre o número de dias entre eles e determine as horas de trabalho.