简体   繁体   English

Oracle SQL 小时时差

[英]Oracle SQL Time Difference in hours

I'm trying to find a way to get the holiday hours while comparing two dates.我试图找到一种方法来比较两个日期的假期时间。

the query below at the moment excludes the holidays and returns the working hours.目前下面的查询不包括假期并返回工作时间。 I'm struggling to get it the other way.我正在努力以另一种方式得到它。 Just to return number of hours of holidays which falls between start and end date.只是返回开始日期和结束日期之间的假期小时数。

If the start date is of 15-04-22 16:00 and its a holiday then query should only return hours b/w 16:00 - 18:00.如果开始日期是 15-04-22 16:00 并且它是一个假期,那么查询应该只返回 b/w 16:00 - 18:00 的小时数。 (work hours would be between 7: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;

Have been stuck at it for more than couple of hours now:|现在已经坚持了几个多小时:|

You can get the number of holiday hours using:您可以使用以下方法获取假期小时数:

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;
/

Which, for the sample data, outputs 22 .其中,对于样本数据,输出22


Additionally, you do not need to use a recursive query to get the number of days and can directly calculate it using:此外,您不需要使用递归查询来获取天数,可以使用以下方法直接计算:

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;
/

Which outputs: 28.5689 (33 hours for 3 full days less 1.5 hours at the end and almost 3 hours at the start).输出: 28.5689 (3 天 33 小时,结束时减去 1.5 小时,开始时将近 3 小时)。

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

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