首页 > 数据库 > mysql教程 > 如何计算 PostgreSQL 中两个日期之间的工作时间?

如何计算 PostgreSQL 中两个日期之间的工作时间?

Linda Hamilton
发布: 2024-12-31 12:15:09
原创
882 人浏览过

How to Calculate Working Hours Between Two Dates in PostgreSQL?

计算 PostgreSQL 中两个日期之间的工作时间

计算特定时间戳之间的工作时间时,需要考虑周末和指定的工作时间。在 PostgreSQL 中,我们可以利用各种技术来完成此任务。

舍入结果

对于特定时间戳范围:

以 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 <= '14:00';
登录后复制

对于整个表:

-- Table Creation and Data Insertion
CREATE TABLE t (t_id int PRIMARY KEY, t_start timestamp, t_end timestamp);
INSERT INTO t VALUES
  (1, '2009-12-03 14:00', '2009-12-04 09:00')
, (2, '2009-12-03 15:00', '2009-12-07 08:00')
, (3, '2013-06-24 07:00', '2013-06-24 12:00')
, (4, '2013-06-24 12:00', '2013-06-24 23:00')
, (5, '2013-06-23 13:00', '2013-06-25 11:00')
, (6, '2013-06-23 14:01', '2013-06-24 08:59');

-- Main Query
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;
登录后复制

更精确的结果

要获得更高的精度,请使用更小的值时间单位,例如 5 分钟切片。

-- Precision with 5-minute Slices
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'  -- 15.00 - interval '5 min'
GROUP  BY 1
ORDER  BY 1;
登录后复制

精确结果

要获得精确到微秒的结果,请分别处理开始和结束时间。

Postgres 8.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)
登录后复制

以上是如何计算 PostgreSQL 中两个日期之间的工作时间?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板