繁体   English   中英

Oracle SQL 小时时差

[英]Oracle SQL Time Difference in hours

我试图找到一种方法来比较两个日期的假期时间。

目前下面的查询不包括假期并返回工作时间。 我正在努力以另一种方式得到它。 只是返回开始日期和结束日期之间的假期小时数。

如果开始日期是 15-04-22 16:00 并且它是一个假期,那么查询应该只返回 b/w 16:00 - 18:00 的小时数。 (工作时间为7:00-18:00)


create table holidays_tb(
holiday_date date
);

insert into holidays_tb values (TO_DATE('15/04/2022', 'DD/MM/YYYY')); 
insert into holidays_tb values (TO_DATE('18/04/2022', 'DD/MM/YYYY'));


declare
v_st_date date;
v_end_date date;
return_val number;
begin
v_st_date := TO_DATE('13/04/2022 09:55:52', 'DD/MM/YYYY HH24:MI:SS'); 
v_end_date := TO_DATE('19/04/2022 16:30:00', 'DD/MM/YYYY HH24:MI:SS'); 
with all_days as
            (select trunc(v_st_date) + level - 1 as a_dt
            from dual
              connect by level <= 1 + (v_end_date - v_st_date)
            minus
            select holiday_date from holidays_tb
            )
          select sum (11)
          into return_val
          from all_days
          where TO_CHAR ( a_dt , 'Dy') NOT IN ('Sat', 'Sun');
dbms_output.put_line(  return_val );        
end;

现在已经坚持了几个多小时:|

您可以使用以下方法获取假期小时数:

DECLARE
  v_st_date  date := DATE '2022-04-13' + INTERVAL '0 09:55:52' DAY TO SECOND;
  v_end_date date := DATE '2022-04-19' + INTERVAL '0 16:30:00' DAY TO SECOND;
  v_work_day_start INTERVAL DAY(0) TO SECOND(0) := INTERVAL '0 07:00:00' DAY TO SECOND;
  v_work_day_end   INTERVAL DAY(0) TO SECOND(0) := INTERVAL '0 18:00:00' DAY TO SECOND;
  v_hours NUMBER := EXTRACT(HOUR FROM v_work_day_end - v_work_day_start)
                  + EXTRACT(MINUTE FROM v_work_day_end - v_work_day_start)/60
                  + EXTRACT(MINUTE FROM v_work_day_end - v_work_day_start)/3600;
  v_holiday NUMBER;
  return_val number;
BEGIN
  SELECT SUM(
           LEAST(holiday_date + v_work_day_end, v_end_date)
           - GREATEST(holiday_date + v_work_day_start, v_st_date)
         ) * 24
  INTO   v_holiday
  FROM   holidays_tb
  WHERE  holiday_date BETWEEN TRUNC(v_st_date) AND v_end_date
  AND    holiday_date - TRUNC(holiday_date, 'IW') < 5;

  DBMS_OUTPUT.PUT_LINE( v_holiday );
END;
/

其中,对于样本数据,输出22


此外,您不需要使用递归查询来获取天数,可以使用以下方法直接计算:

DECLARE
  v_st_date  date := DATE '2022-04-13' + INTERVAL '0 09:55:52' DAY TO SECOND;
  v_end_date date := DATE '2022-04-19' + INTERVAL '0 16:30:00' DAY TO SECOND;
  v_work_day_start INTERVAL DAY(0) TO SECOND(0) := INTERVAL '0 07:00:00' DAY TO SECOND;
  v_work_day_end   INTERVAL DAY(0) TO SECOND(0) := INTERVAL '0 18:00:00' DAY TO SECOND;
  v_hours NUMBER := EXTRACT(HOUR FROM v_work_day_end - v_work_day_start)
                  + EXTRACT(MINUTE FROM v_work_day_end - v_work_day_start)/60
                  + EXTRACT(MINUTE FROM v_work_day_end - v_work_day_start)/3600;
  v_holiday NUMBER;
  return_val number;
BEGIN
  SELECT SUM(
           LEAST(holiday_date + v_work_day_end, v_end_date)
           - GREATEST(holiday_date + v_work_day_start, v_st_date)
         ) * 24
  INTO   v_holiday
  FROM   holidays_tb
  WHERE  holiday_date BETWEEN TRUNC(v_st_date) AND v_end_date
  AND    holiday_date - TRUNC(holiday_date, 'IW') < 5;

  return_val :=
    -- Full weeks
    (TRUNC(v_end_date, 'IW') - TRUNC(v_st_date, 'IW')) * 5 / 7 * v_hours
    -- Full days before in start week
    - LEAST(TRUNC(v_st_date) - TRUNC(v_st_date, 'IW'), 5) * v_hours
    -- Part days before in start week
    - CASE
      WHEN v_st_date - TRUNC(v_st_date, 'IW') < 5
      THEN LEAST(
             GREATEST(
               (v_st_date - (TRUNC(v_st_date) + v_work_day_start))* 24,
               0
             ),
             v_hours
           )
      ELSE 0
      END
    -- End full days
    + LEAST(TRUNC(v_end_date) - TRUNC(v_end_date, 'IW'), 5) * v_hours
    -- End part days
    + CASE
      WHEN v_end_date - TRUNC(v_end_date, 'IW') < 5
      THEN LEAST(
             GREATEST(
               (v_end_date - (TRUNC(v_end_date) + v_work_day_start))* 24,
               0
             ),
             v_hours
           )
      ELSE 0
      END
    -- Holiday hours
    - v_holiday;
    
  DBMS_OUTPUT.PUT_LINE( return_val );        
END;
/

输出: 28.5689 (3 天 33 小时,结束时减去 1.5 小时,开始时将近 3 小时)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM