Sql 从非工作日计数中删除重叠小时数

Sql 从非工作日计数中删除重叠小时数,sql,oracle,Sql,Oracle,需要您的帮助才能完成此任务 二月总共有696小时 Start Date End Date S1 - 01-Feb-16 04:00 - 02-Feb-16 10:00 - 30hrs S2 - 02-Feb-16 14:00 - 06-Feb-16 20:00 - 102hrs S3 - 01-Feb-16 01:00 - 02-Feb-16 07:00 - 30hrs Total Worked hrs - 162 hrs 由于S

需要您的帮助才能完成此任务

二月总共有696小时

     Start Date        End Date 
S1 - 01-Feb-16 04:00 - 02-Feb-16 10:00 - 30hrs
S2 - 02-Feb-16 14:00 - 06-Feb-16 20:00 - 102hrs
S3 - 01-Feb-16 01:00 - 02-Feb-16 07:00 - 30hrs

                Total Worked hrs   - 162 hrs
由于S1和S3的可用时间重叠为27小时,因此总工作时间为135小时 预期查询结果为561小时

我对代码有一个挑战 1.代码准备好了,除了忽略重叠时间之外,其他部分需要您的帮助。 2.如何将查询限制为仅对sysdate月进行验证

Query: 
SELECT ( ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 ) - TRUNC( SYSDATE, 'MM' )
         - SUM( End_Date - Start_Date ) ) * 24 AS Unworked_Hours
FROM   Trip_Dates;

Oracle安装程序

CREATE TABLE Trip_Dates ( Start_Date, End_Date ) AS
SELECT TO_DATE( '2016-02-01 04:00:00', 'YYYY-MM-DD HH24:MI:SS' ), TO_DATE( '2016-02-02 10:00:00', 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL UNION ALL
SELECT TO_DATE( '2016-02-02 14:00:00', 'YYYY-MM-DD HH24:MI:SS' ), TO_DATE( '2016-02-06 20:00:00', 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL UNION ALL
SELECT TO_DATE( '2016-02-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS' ), TO_DATE( '2016-02-02 07:00:00', 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL;
WITH Dates ( dt, start_end ) AS (
  SELECT GREATEST( start_date, TRUNC( SYSDATE, 'MM' ) ),
         1
  FROM   trip_dates
  WHERE  start_date < ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 )
  AND    end_date > TRUNC( SYSDATE, 'MM' )
  UNION ALL
  SELECT LEAST( end_date, ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 ) ),
         -1
  FROM trip_dates
  WHERE  start_date < ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 )
  AND    end_date > TRUNC( SYSDATE, 'MM' )
  ORDER BY 1, 2
)
,range_start_ends ( dt, start_end, range_start, range_end ) AS (
  SELECT d.*,
         CASE
           WHEN start_end =  1
            AND SUM( start_end ) OVER ( ORDER BY dt ) = 1
           THEN dt
           ELSE NULL
            END,
         CASE
           WHEN start_end = -1
            AND SUM( start_end ) OVER ( ORDER BY dt ) = 0
           THEN dt
           ELSE NULL
            END
  FROM   Dates d
),
worked_days ( worked_days ) AS (
  SELECT range_end - LAG( range_start ) IGNORE NULLS OVER ( ORDER BY dt )
  FROM   range_start_ends
)
SELECT ( ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 )
        - TRUNC( SYSDATE, 'MM' ) -
        SUM( worked_days )
       ) * 24 AS unworked_hours
FROM   worked_days;
UNWORKED_HOURS
--------------
           561 
查询

CREATE TABLE Trip_Dates ( Start_Date, End_Date ) AS
SELECT TO_DATE( '2016-02-01 04:00:00', 'YYYY-MM-DD HH24:MI:SS' ), TO_DATE( '2016-02-02 10:00:00', 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL UNION ALL
SELECT TO_DATE( '2016-02-02 14:00:00', 'YYYY-MM-DD HH24:MI:SS' ), TO_DATE( '2016-02-06 20:00:00', 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL UNION ALL
SELECT TO_DATE( '2016-02-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS' ), TO_DATE( '2016-02-02 07:00:00', 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL;
WITH Dates ( dt, start_end ) AS (
  SELECT GREATEST( start_date, TRUNC( SYSDATE, 'MM' ) ),
         1
  FROM   trip_dates
  WHERE  start_date < ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 )
  AND    end_date > TRUNC( SYSDATE, 'MM' )
  UNION ALL
  SELECT LEAST( end_date, ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 ) ),
         -1
  FROM trip_dates
  WHERE  start_date < ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 )
  AND    end_date > TRUNC( SYSDATE, 'MM' )
  ORDER BY 1, 2
)
,range_start_ends ( dt, start_end, range_start, range_end ) AS (
  SELECT d.*,
         CASE
           WHEN start_end =  1
            AND SUM( start_end ) OVER ( ORDER BY dt ) = 1
           THEN dt
           ELSE NULL
            END,
         CASE
           WHEN start_end = -1
            AND SUM( start_end ) OVER ( ORDER BY dt ) = 0
           THEN dt
           ELSE NULL
            END
  FROM   Dates d
),
worked_days ( worked_days ) AS (
  SELECT range_end - LAG( range_start ) IGNORE NULLS OVER ( ORDER BY dt )
  FROM   range_start_ends
)
SELECT ( ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 )
        - TRUNC( SYSDATE, 'MM' ) -
        SUM( worked_days )
       ) * 24 AS unworked_hours
FROM   worked_days;
UNWORKED_HOURS
--------------
           561