如何計算Oracle 10g中兩個日期之間的工作時間或天數?如何在兩個日期之間獲得工作日或小時
例如,我們有兩個日期; 2012年4月14日9:30和16/08/2012 12:00我們的工作時間爲平日09:30至18:30。
如何計算工作時間或天數,不包括國定假日,週六& Sun with oracle 10g?
如何計算Oracle 10g中兩個日期之間的工作時間或天數?如何在兩個日期之間獲得工作日或小時
例如,我們有兩個日期; 2012年4月14日9:30和16/08/2012 12:00我們的工作時間爲平日09:30至18:30。
如何計算工作時間或天數,不包括國定假日,週六& Sun with oracle 10g?
你不行。就這麼簡單。全國各地的節日不盡相同,它們逐年變化,並且隨時可以添加或帶走額外的節日。此外,一些司法管轄區承載週末的國定假日,並在下週舉行會議;別人不會。
您需要創建一個日曆表並在此標記國家節假日/週末等。
例如
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'
發現計算工作時間不包括表週末和節假日列表中的解決方案。
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 ;
我只是做了類似的東西。下面是一個SQL代碼塊由員工在一個表來計算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函數,看看它是如何工作的通過爲各行一天工作。
此外,對於像銀行這樣的特殊業務,可能會定義不同的工作日。例如在德國'聖誕夜'和'除夕'不是國定假日,而是國家銀行假日。 – 2012-08-14 13:34:54
嗨本我嘗試了你的選擇,但我卡在插入數據它給我ORA-01846錯誤 – leelavinodh 2012-08-30 13:09:03
而不是to_Date我用to_char然後我能夠插入數據到日曆表。但如何計算工作時間? – leelavinodh 2012-08-30 13:47:40