計算PostgreSQL 中日期之間的工作時間
簡介
在各種場景中,確定兩個時間戳之間的工作小時數在工資單和調度等領域被證明是至關重要的。在 PostgreSQL 中,此計算需要仔細考慮工作日和特定時間的參數。本文概述了一個全面的解決方案,考慮到以下標準:
解決方案
方法1:四捨五入僅兩個時間戳的結果
此方法適用於以1 小時為單位,忽略小數小時。這是一種簡單但不太精確的方法。
查詢:
SELECT count(*) AS work_hours FROM generate_series (timestamp '2013-06-24 13:30' , timestamp '2013-06-24 15:29' - interval '1h' , interval '1h') h WHERE EXTRACT(ISODOW FROM h) < 6 AND h::time >= '08:00' AND h::time &lt;= '14:00';
範例輸入:
2013-06-24 13:30, 2013-06-24 15:29
輸出:
2
方法2:時間戳表的捨入結果
這種方法擴展了先前的方法來處理時間戳表
查詢:SELECT t_id, count(*) AS work_hours FROM ( SELECT t_id, generate_series (t_start, t_end - interval '1h', interval '1h') AS h FROM t ) sub WHERE EXTRACT(ISODOW FROM h) < 6 AND h::time >= '08:00' AND h::time <= '14:00' GROUP BY 1 ORDER BY 1;
方法三:更精確的計算
對於較細微的計算,較小的時間單位可以是已考慮。
查詢:SELECT t_id, count(*) * interval '5 min' AS work_interval FROM ( SELECT t_id, generate_series (t_start, t_end - interval '5 min', interval '5 min') AS h FROM t ) sub WHERE EXTRACT(ISODOW FROM h) < 6 AND h::time >= '08:00' AND h::time <= '14:55' GROUP BY 1 ORDER BY 1;
範例輸入:
| t_id | t_start | t_end | |------|-------------------------|-------------------------| | 1 | 2009-12-03 14:00:00 | 2009-12-04 09:00:00 | | 2 | 2009-12-03 15:00:00 | 2009-12-07 08:00:00 | | 3 | 2013-06-24 07:00:00 | 2013-06-24 12:00:00 | | 4 | 2013-06-24 12:00:00 | 2013-06-24 23:00:00 | | 5 | 2013-06-23 13:00:00 | 2013-06-25 11:00:00 | | 6 | 2013-06-23 14:01:00 | 2013-06-24 08:59:00 |
輸出:
| t_id | work_interval | |------|----------------| | 1 | 1 hour | | 2 | 8 hours | | 3 | 0 hours | | 4 | 0 hours | | 5 | 6 hours | | 6 | 1 hour |
方法4:精確結果
此方法提供微秒精度的精確結果。它更複雜,但計算效率更高。
WITH var AS (SELECT '08:00'::time AS v_start , '15:00'::time AS v_end) SELECT t_id , COALESCE(h.h, '0') -- add / subtract fractions - CASE WHEN EXTRACT(ISODOW FROM t_start) < 6 AND t_start::time > v_start AND t_start::time < v_end THEN t_start - date_trunc('hour', t_start) ELSE '0'::interval END + CASE WHEN EXTRACT(ISODOW FROM t_end) < 6 AND t_end::time > v_start AND t_end::time < v_end THEN t_end - date_trunc('hour', t_end) ELSE '0'::interval END AS work_interval FROM t CROSS JOIN var LEFT JOIN ( -- count full hours, similar to above solutions SELECT t_id, count(*)::int * interval '1h' AS h FROM ( SELECT t_id, v_start, v_end , generate_series (date_trunc('hour', t_start) , date_trunc('hour', t_end) - interval '1h' , interval '1h') AS h FROM t, var ) sub WHERE EXTRACT(ISODOW FROM h) < 6 AND h::time >= v_start AND h::time <= v_end - interval '1h' GROUP BY 1 ) h USING (t_id) ORDER BY 1;
查詢:
這個全面的解決方案解決了在 PostgreSQL 中準確高效地計算工作時間的需求。以上是如何計算 PostgreSQL 中日期之間的工作時間(考慮週末和特定工作時間)?的詳細內容。更多資訊請關注PHP中文網其他相關文章!