用移位计算SQL中的时间差异

时间:2018-05-31 13:03:30

标签: sql oracle

我有两张桌子 第一个表包含具有开始日期和结束日期的票证记录

 start_date           | End_Date
 21-02-2017 07:52:32  | 22-02-2017 09:56:32
 21-02-2017 09:52:32  | 23-02-2017 17:52:32

第二个表格包含每周班次的详细信息:

 shift_day | Start_Time | End_Time
  MON        9:00          18:00
  TUE        10:00         19:00
  WED        9:00          18:00
  THU        10:00         19:00
  FRI        9:00          18:00

我希望在第一个表中获得时间差,其中仅包括第二个表的时间。

1 个答案:

答案 0 :(得分:0)

使用递归子查询分解子句在您的时间范围内生成每一天,然后将其与您的班次相关联,以将每天的时间限制在班次小时内,然后汇总以获得总数:

Oracle 18设置

CREATE TABLE times ( start_date, End_Date ) AS
SELECT DATE '2017-02-21' + INTERVAL '07:52:32' HOUR TO SECOND,
       DATE '2017-02-22' + INTERVAL '09:56:32' HOUR TO SECOND
FROM   DUAL
UNION ALL
SELECT DATE '2017-02-21' + INTERVAL '09:52:32' HOUR TO SECOND,
       DATE '2017-02-23' + INTERVAL '17:52:32' HOUR TO SECOND
FROM   DUAL;

CREATE TABLE weekly_shifts ( shift_day, Start_Time, End_Time ) AS
SELECT 'MON', INTERVAL '09:00' HOUR TO MINUTE, INTERVAL '18:00' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT 'TUE', INTERVAL '10:00' HOUR TO MINUTE, INTERVAL '19:00' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT 'WED', INTERVAL '09:00' HOUR TO MINUTE, INTERVAL '18:00' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT 'THU', INTERVAL '10:00' HOUR TO MINUTE, INTERVAL '19:00' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT 'FRI', INTERVAL '09:00' HOUR TO MINUTE, INTERVAL '18:00' HOUR TO MINUTE FROM DUAL;

查询1

WITH days ( id, start_date, day_start, day_end, end_date ) AS (
  SELECT ROWNUM,
         start_date,
         start_date,
         LEAST( TRUNC( start_date ) + INTERVAL '1' DAY, end_date ),
         end_date
  FROM   times
UNION ALL
  SELECT id,
         start_date,
         day_end,
         LEAST( day_end + INTERVAL '1' DAY, end_date ),
         end_date
  FROM   days
  WHERE  day_end < end_date
)
SELECT start_date,
       end_date,
       SUM( shift_end - shift_start ) AS days_worked_on_shift
FROM   (
  SELECT ID,
         start_date,
         end_date,
         GREATEST( day_start, TRUNC( day_start ) + start_time ) AS shift_start,
         LEAST( day_end, TRUNC( day_start ) + end_time ) AS shift_end
  FROM   days d
         INNER JOIN
         weekly_shifts w
         ON ( TO_CHAR( d.day_start, 'DY' ) = w.shift_day )
)
GROUP BY id, start_date, end_date;

<强>结果

START_DATE          END_DATE            DAYS_WORKED_ON_SHIFT
------------------- ------------------- --------------------
2017-02-21 07:52:32 2017-02-22 09:56:32 0.414259259259259259
2017-02-21 09:52:32 2017-02-23 17:52:32 1.078148148148148148
相关问题