Jag skulle föreslå att du genererar alla intervall för öppettider mellan created_at
och aktuell_tidsstämpel och summera dem. Även om det är långt ifrån optimal lösning när det gäller prestanda, tror jag att det är det mest enkla tillvägagångssättet. Jag använder tidsstämpel med tidszonintervall tstzrange
med korsning operatör (*)
.
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
Se inställningen och exemplet i db<>fiol
Varning
Även om implementeringen gjordes för att vara lätt att förstå och felsöka kan den resultera i dålig prestanda - speciellt om den används med mycket gamla create_at-datum. Om så kan vara fallet i ditt system kan det vara bättre för dig att skriva en funktion som kontrollerar veckodagen för create_at och current_date, hittar antalet dagar mellan dem och bestämmer arbetstimmar.