Oracle SQL - 如何计算两个日期之间的工作时间和分钟数

Oracle SQL - How to work out the working hours and minutes between two dates

Oracle SQL 有没有办法找出两个日期之间的工作小时数和分钟数?

举个例子

工作日为周一至周五上午 8 点至下午 5 点

Job.Job_Logged     Job.Actual_Start_Date       Time Elapsed
01/08/2019 10:00   01/08/2019  12:32           2:32
01/08/2019 16:00   02/08/2019  09:00           3:00

我没有检查可能的重复项,但一种方法是递归查询:

with cte(id, start_date, end_date, hd1, hd2) as (
    select id, cast(start_date as date), cast(end_date as date), cast(start_date as date), 
           cast(least(end_date, trunc(start_date) + 17/24) as date)
      from jobs 
    union all 
    select id, start_date, end_date, cast(trunc(hd1) + 1 + 8/24 as date), 
           cast(least(trunc(hd1) + 1 + 17/24, end_date) as date)
      from cte
      where trunc(hd1) + 1 + 8/24 < end_date)
select id, start_date, end_date, dbms_xplan.format_time_s(sum(hd2 - hd1) * 24 * 60) hours
  from cte
  where to_char(hd1, 'd') not in (6, 7)
  group by id, start_date, end_date

dbfiddle demo

我使用 17/24 的地方表示结束时间 17:008/24 - 开始时间,not in (6, 7) 不包括周六和周日。

编辑1:最后应该是24 * 60 * 60 select.

编辑 2: 要使查询独立于 nls_settings 使用:

to_char(hd1, 'Dy', 'nls_date_language=english') not in ('Sat', 'Sun')

dbfiddle demo


the version of Oracle I'm using insists on having SELECT as the first word in any code

这种递归查询从Oracle version 11开始就有了。我不知道你的工具是否需要在第一行使用select或者是这个版本的问题,但是在第一种情况下你可以将RCTE移动到from 子句:

select id, start_date, end_date, dbms_xplan.format_time_s(sum(hd2 - hd1) * 24 * 60 * 60) hours
  from (
    with
      cte(id, start_date, end_date, hd1, hd2) as (
        select id, cast(start_date as date), cast(end_date as date), cast(start_date as date),
               cast(least(end_date, trunc(start_date) + 17/24) as date)
          from jobs
        union all
        select id, start_date, end_date, cast(trunc(hd1) + 1 + 8/24 as date),
               cast(least(trunc(hd1) + 1 + 17/24, end_date) as date)
          from cte
          where trunc(hd1) + 1 + 8/24 < end_date)
     select * from cte 
       where to_char(hd1, 'Dy', 'nls_date_language=english') not in ('Sat', 'Sun') )
  group by id, start_date, end_date

fiddle