簡體   English   中英

如何消除Oracle中的非工作時間

[英]How to eliminate non-working hours in Oracle

我有兩列DateTime類型。 第一個在啟動進程時存儲DateTime,另一個在該進程完成時存儲DateTime。 我想計算完成工作所需的總工時。 工作時間是上午10點到晚上7點,周日休息。

以下是我記下的一些片段:

       SELECT col1, col2, floor(((date2-date1)*24*60*60)/3600)
       || ' HOURS ' ||
       floor((((date2-date1)*24*60*60) -
       floor(((date2-date1)*24*60*60)/3600)*3600)/60)
       || ' MINUTES ' ||
       round((((date2-date1)*24*60*60) -
       Floor(((date2-date1)*24*60*60)/3600)*3600 -
       (floor((((date2-date1)*24*60*60) -
       floor(((date2-date1)*24*60*60)/3600)*3600)/60)*60) ))
       || ' SECS ' Time_Difference
       From Table_Name;

和,

       Select To_Number(To_Char(date1, 'HH24')) || ':'
       ||   to_number(to_char(date1, 'MI')) || ':'||
       to_number(to_char(date1, 'SS')) from Table_Name

請幫忙。


對於你提到的上述解決方案,這就是結果!

START DATE          DAY     FINISH DATE     DAY  Date Diff   Total Hours   Work Hours 

07-AUG-12 21:55:21  TUE 08-AUG-12 11:09:10  WED 0 13:13:49.0        13   13 
13-NOV-12 15:45:25  TUE 14-NOV-12 10:41:42  WED 0 18:56:17.0        18   18 
20-DEC-12 20:31:03  THU 21-DEC-12 11:03:36  FRI 0 14:32:33.0        14   14 
14-MAR-13 20:39:00  THU 15-MAR-13 11:00:04  FRI 0 14:21:4.0         14   14 
07-JUN-12 21:17:36  THU 08-JUN-12 11:02:23  FRI 0 13:44:47.0        13   13 
18-SEP-12 20:48:27  TUE 19-SEP-12 11:07:35  WED 0 14:19:8.0         14   14 

新方案: https//stackoverflow.com/questions/17248741/how-to-get-business-hours-between-two-dates-in-oracle

如果我理解正確,你想計算開始和結束日期之間的差異,不包括上午10點之前和晚上7點之后的時間。

這是示例查詢和sql小提琴

SELECT start_time,
       finish_time,
       interval_time,
       EXTRACT (HOUR FROM interval_time), --extract the hours,mins and seconds from the interval
       EXTRACT (MINUTE FROM interval_time),
       EXTRACT (SECOND FROM interval_time)
  FROM (SELECT start_time,
               finish_time,
               NUMTODSINTERVAL (
                    CASE
                       WHEN finish_time - TRUNC (finish_time) > (19 / 24) --if finish time is after 7pm
                       THEN
                          TRUNC (finish_time) + (19 / 24)      --set it to 7pm
                       ELSE
                          finish_time      --else set it to actual finish time
                    END
                  - CASE
                       WHEN start_time - TRUNC (start_time) < (10 / 24) --if start time is before 10 am
                       THEN
                          TRUNC (start_time) + (10 / 24)    --set it to 10 am.
                       ELSE
                          start_time    --else set it to the actual start time
                    END,
                  'day') --subtract the both and convert the resulting day to interval
                  interval_time
          FROM timings);

我做的是,

  • 檢查開始時間是否在上午10點之前,結束時間是在晚上7點之后。 如果是這樣,請將時間設置為上午10點和下午7點。
  • 然后減去日期並將結果日期轉換為間隔類型。
  • 然后從Interval中提取小時,分鍾和秒。

注意:此查詢假定兩個日期都在同一天,而且都不是在上午10點之前或下午7點之后。

更新:要排除假期,查詢將變得復雜。 我建議編寫三個函數並在查詢中使用這些函數。

第一功能:

FUNCTION modify_start_time (p_in_dte DATE) RETURN DATE
----------------------------------
IF p_in_dte - TRUNC (p_in_dte) < (10 / 24)
THEN
   RETURN TRUNC (p_in_dte) + (10 / 24);
ELSIF p_in_dte - TRUNC (p_in_dte) > (19 / 24)
THEN
   RETURN TRUNC (p_in_dte) + 1 + (10 / 24);
ELSE
   RETURN p_in_dte;
END IF;

如果開始時間超出工作時間,請將開始時間修改為下一個最近的開始時間。

第二功能:

FUNCTION modify_finish_time (p_in_dte DATE) RETURN DATE
----------------------------------
IF p_in_dte - TRUNC (p_in_dte) > (19 / 24)
THEN
   RETURN TRUNC (p_in_dte) + (19 / 24);
ELSIF p_in_dte - TRUNC (p_in_dte) < (10 / 24)
THEN
   RETURN TRUNC (p_in_dte) - 1 + (19 / 24);
ELSE
   RETURN p_in_dte;
END IF;

如果完成時間超出工作時間,請將其修改為上一個最接近的完成時間。

第三功能:

FUNCTION get_days_to_exclude (p_in_start_date     DATE,
                              p_in_finish_date    DATE) RETURN NUMBER
--------------------------------------------------------
WITH cte --get all days between start and finish date
     AS (    SELECT p_in_start_date + LEVEL - 1 dte
               FROM DUAL
         CONNECT BY LEVEL <= p_in_finish_date + 1 - p_in_starT_date)
SELECT COUNT (1) * 9 / 24    --mutiply the days with work hours in a day
  INTO l_num_holidays
  FROM cte
 WHERE    TO_CHAR (dte, 'dy') = 'sun'    --find the count of sundays
       OR dte IN     --fins the count of holidays, assuming leaves are stored in separate table
             (SELECT leave_date  
                FROM leaves
               WHERE leave_date BETWEEN p_in_start_date
                                    AND p_in_finish_date);

l_num_holidays :=
   l_num_holidays + ( (p_in_finish_date - p_in_start_date) * (15 / 24)); --also, if the dates span more than a day find the non working hours.

RETURN l_num_holidays;

此函數在計算持續時間時查找要排除的天數。

所以,最終的查詢應該是這樣的,

SELECT start_time,
       finish_time,
       CASE
          WHEN work_duration < 0 THEN NUMTODSINTERVAL (0, 'day')
          ELSE NUMTODSINTERVAL (work_duration, 'day')
       END
  FROM (SELECT start_time, finish_time,
               --modify_start_time (start_time), modify_finish_time (finish_time),
                 modify_finish_time (finish_time)
               - modify_start_time (start_time)
               - get_days_to_exclude (
                    TRUNC (modify_start_time (start_time)),
                    TRUNC (modify_finish_time (finish_time)))
                  work_duration
          FROM timings);

如果持續時間小於0,則通過將其設置為0來忽略它。

您可以記錄兩個日期之間的小時差異,並減少兩天之間的非工作小時數。 考慮這個例子:

create table t1 (
    start_hour date , finish_hour date);

insert into t1 values (
  to_date('01/01/2013 12:00:00','dd/mm/yyyy hh24:mi:ss'),
  to_date('01/01/2013 15:00:00','dd/mm/yyyy hh24:mi:ss'));

insert into t1 values (
  to_date('01/01/2013 12:00:00','dd/mm/yyyy hh24:mi:ss'),
  to_date('02/01/2013 15:00:00','dd/mm/yyyy hh24:mi:ss'));

insert into t1 values (
  to_date('01/01/2013 18:00:00','dd/mm/yyyy hh24:mi:ss'),
  to_date('03/01/2013 11:00:00','dd/mm/yyyy hh24:mi:ss'));


with x as (
select start_hour ,finish_hour , 
      (finish_hour - start_hour) * 24 hour_diff , 
       trunc(finish_hour) - trunc(start_hour) as day_diff
from t1
) 
select  start_hour , finish_hour , 
        hour_diff - 15 * day_diff as working_hours 
from x;

|                     START_HOUR |                    FINISH_HOUR | WORKING_HOURS |
-----------------------------------------------------------------------------------
| January, 01 2013 12:00:00+0000 | January, 01 2013 15:00:00+0000 |             3 |
| January, 01 2013 12:00:00+0000 | January, 02 2013 15:00:00+0000 |            12 |
| January, 01 2013 18:00:00+0000 | January, 03 2013 11:00:00+0000 |            11 |

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM