2012-08-14 84 views
1

如何計算Oracle 10g中兩個日期之間的工作時間或天數?如何在兩個日期之間獲得工作日或小時

例如,我們有兩個日期; 2012年4月14日9:30和16/08/2012 12:00我們的工作時間爲平日09:30至18:30。

如何計算工作時間或天數,不包括國定假日,週六& Sun with oracle 10g?

回答

0

你不行。就這麼簡單。全國各地的節日不盡相同,它們逐年變化,並且隨時可以添加或帶走額外的節日。此外,一些司法管轄區承載週末的國定假日,並在下週舉行會議;別人不會。

您需要創建一個日曆表並在此標記國家節假日/週末等。

例如

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' 
+0

此外,對於像銀行這樣的特殊業務,可能會定義不同的工作日。例如在德國'聖誕夜'和'除夕'不是國定假日,而是國家銀行假日。 – 2012-08-14 13:34:54

+0

嗨本我嘗試了你的選擇,但我卡在插入數據它給我ORA-01846錯誤 – leelavinodh 2012-08-30 13:09:03

+0

而不是to_Date我用to_char然後我能夠插入數據到日曆表。但如何計算工作時間? – leelavinodh 2012-08-30 13:47:40

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

我只是做了類似的東西。下面是一個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函數,看看它是如何工作的通過爲各行一天工作。

相關問題