sql >> Base de Datos >  >> RDS >> PostgreSQL

Diferencia horaria dentro del horario laboral

Sugeriría generar todos los rangos de horas de trabajo entre created_at y current_timestamp y sumarlos. Si bien está lejos de ser una solución óptima en términos de rendimiento, creo que es el enfoque más directo. Uso la marca de tiempo con el rango de zona horaria rango tstz con intersección 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

Consulte la configuración y el ejemplo en db<>fiddle

Palabra de precaución

Si bien la implementación se hizo para que fuera fácil de entender y depurar, puede resultar en un rendimiento deficiente, especialmente si se usa con fechas created_at muy antiguas. Si ese es el caso en su sistema, es mejor que escriba una función que verifique el día de la semana de created_at y current_date, encuentre la cantidad de días entre ellos y determine las horas de trabajo.