如何在oracle 10g中计算两个日期之间的营业时间或天数?
例如,我们有两个日期: 14/08/2012 9:30和16/08/2012 12:00,工作日的工作时间是09:30到18:30。
如何使用oracle 10g计算不包括国家假日、星期六和星期日的工作时间或天数?
发布于 2012-08-14 21:23:44
你不能。就这么简单。世界各地的国家假日各不相同,每年都不同,额外的假日可以随时增加或取消。此外,一些司法辖区延续了周末的国家假日,并在下一周放假;其他司法辖区则没有。
您将需要创建一个日历表,并在此标记国家假日/周末等。
例如
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-09-06 03:55:12
在表格中找到了计算不包括周末和节假日的营业时间的解决方案。
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 ;
发布于 2014-04-21 17:05:55
我刚做了这样的事。下面是一段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
您可以删除group by行并删除sum函数,以便通过为每天工作生成行来查看它是如何工作的。
https://stackoverflow.com/questions/11953134
复制相似问题