Tôi khuyên bạn nên tạo tất cả các phạm vi giờ làm việc giữa created_at
và current_timestamp và tính tổng chúng. Mặc dù còn lâu mới là giải pháp tối ưu về mặt hiệu suất, tôi nghĩ đó là cách tiếp cận dễ hiểu nhất. Tôi sử dụng dấu thời gian với phạm vi múi giờ tstzrange
với giao lộ toán tử (*)
.
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
Xem thiết lập và ví dụ trong db <> fiddle
Lời cảnh báo
Mặc dù việc triển khai được thực hiện để dễ hiểu và dễ gỡ lỗi, nó có thể dẫn đến hiệu suất kém - đặc biệt nếu được sử dụng với các ngày create_at rất cũ. Nếu điều đó có thể xảy ra trong hệ thống của bạn, tốt hơn hết bạn nên viết hàm kiểm tra ngày trong tuần của create_at và current_date, tìm số ngày giữa chúng và xác định giờ làm việc.