1

如何在 oracle 10g 中计算两个日期之间的营业时间或天数?

例如我们有两个日期;14/08/2012 9:30 和 16/08/2012 12:00 我们工作日的工作时间为 09:30 至 18:30。

如何使用 oracle 10g 计算不包括国定假日、周六和周日的工作时间或天数?

4

3 回答 3

1

你不能。就这么简单。世界各地的国定假日各不相同,每年都有所不同,并且可以随时增加或取消额外的假期。此外,一些司法管辖区会将周末的国定假日延续到下周;其他人没有。

您需要在此创建一个日历表并标记国定假日/周末等。

例如

create table calender
  ( day date
  , weekend varchar2(1)
  , holiday varchar2(1)
    );

然后在其中插入一些数据...

 insert into calender (day, weekend)
 select trunc(sysdate + level)
      , case when to_date(sysdate + level,'fmDAY') in ('SATURDAY','SUNDAY') 
                  then 'Y' else 'N' end
   from dual
connect by level <= 365

最后,手动更新您认为是国定假日的内容。

然后,您可以选择工作日,具体取决于您使用以下内容填充它的方式:

select count(*)
  from calender
 where day between :startdate and :enddate
   and weekend = 'N'
   and holiday = 'N'
于 2012-08-14T13:23:44.427 回答
0

在表格中找到了计算除周末和节假日之外的营业时间的解决方案。

https://forums.oracle.com/forums/thread.jspa?messageID=9322860

        create or replace
        FUNCTION business_hours(
              in_start_dt IN DATE DEFAULT SYSDATE ,
              in_end_dt   IN DATE DEFAULT SYSDATE )
            RETURN NUMBER DETERMINISTIC
          IS
            --  business_hours returns the number of work hours (9.30 am through 6.30 pm,
            --  Monday through Friday) between in_start_dt and in_end_dt.
            --  If in_start_dt > in_end_dt, the results will be <= 0.
            d          NUMBER;                                    -- Hours of either start_dt or end_dt after midnight
            end_dt     DATE := GREATEST (in_start_dt, in_end_dt); -- In case dates were in wrong order
            return_val NUMBER;                                    -- Total number of working hours
            start_dt   DATE := LEAST (in_start_dt, in_end_dt);    -- In case dates were in wrong order
          BEGIN
          WITH all_days AS
            (SELECT TRUNC(start_dt) + LEVEL - 1 AS a_dt
            FROM dual
              CONNECT BY LEVEL <= 1 + TRUNC (end_dt) - TRUNC (start_dt)
            MINUS
            SELECT hol_dt FROM holiday
            )
          SELECT SUM (9)
          INTO return_val
          FROM all_days
          WHERE TO_CHAR ( a_dt , 'Dy' , 'NLS_DATE_LANGUAGE = ''ENGLISH''' ) NOT IN ('Sat', 'Sun');
          -- Adjust hours from start_dt, if necessary
          IF TO_CHAR ( start_dt , 'Dy' , 'NLS_DATE_LANGUAGE = ''ENGLISH''' ) NOT IN ('Sat', 'Sun') THEN
            d := 24 * (start_dt - TRUNC (start_dt));
            IF d >= 18.5 THEN -- Don't count start_dt itself
              return_val := return_val - 9;
            ELSIF d > 9.5 THEN -- Don't count part of start_dt
              return_val := return_val - (d - 9.5);
            END IF;
          END IF;
          -- Adjust hours from end_dt, if necessary
          IF TO_CHAR ( end_dt , 'Dy' , 'NLS_DATE_LANGUAGE = ''ENGLISH''' ) NOT IN ('Sat', 'Sun') THEN
            d := 24 * (end_dt - TRUNC (end_dt));
            IF d <= 9.5 THEN -- Don't count end_dt itself
              return_val := return_val - 9;
            ELSIF d < 18.5 THEN -- Don't count part of end_dt
              return_val := return_val - (18.5 - d);
            END IF;
          END IF;
          IF in_start_dt > in_end_dt THEN
            return_val  := -return_val;
          END IF;
          RETURN return_val;
        END business_hours ;
于 2012-09-05T19:55:11.947 回答
0

我只是做了类似的事情。这是一个 sql 代码段,用于计算表 T 中员工在 stime 和 etime 之间完成的工作

create table t ( NAME varchar(50), stime date, etime date, clockin number,clockout number );
insert into t values ( 'JOHN', to_date( '18/12/2003 11:40','dd/mm/yyyy hh24:mi'), to_date( '22/12/2003 14:00', 'dd/mm/yyyy hh24:mi'),8, 17 );
insert into t values ( 'JOHN', to_date( '19/12/2003 13:40','dd/mm/yyyy hh24:mi'), to_date( '21/12/2003 15:00', 'dd/mm/yyyy hh24:mi'),8, 17 );
insert into t values ( 'TOM', to_date( '19/12/2003 13:40','dd/mm/yyyy hh24:mi'), to_date( '21/12/2003 15:00', 'dd/mm/yyyy hh24:mi'),8, 17 );


with oo as (SELECT LEVEL-1 rn FROM dual CONNECT BY LEVEL <= 365) --JUST A TABLE WITH INTEGER RECORDS FROM 1 To 365 
select
t.NAME ,sum(least( trunc(stime)+18.5/24+rn, etime )-greatest( stime, trunc(stime)+9.5/24+rn))*24 as WorkHours -- Get workhours between 09:30-18:30 
from oo
inner join t on oo.rn < (trunc(etime)-trunc(stime)+1) 
      and to_char(stime+rn,'Dy') not in ( 'Sat', 'Sun' )  --For eliminating Weekends
      and to_char(trunc(stime)+rn,'DD.MM')  != '04.07'   -- For eliminating Holidays
group by t.NAME 

您可以逐行删除组并删除 sum 函数,以通过为每一天生成行来查看它是如何工作的。

于 2014-04-21T09:05:54.540 回答