Oracle
 sql >> база данни >  >> RDS >> Oracle

Как да премахнете неработното време в Oracle

Ако разбирам правилно, искате да изчислите разликата между началната и крайната дата, с изключение на времето преди 10 сутринта и след 19 часа.

Ето примерната заявка и 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 часа сутринта и часът за край е след 19 часа. Ако е така, задайте часа на 10 сутринта и 19 часа.
  • След това извадете датите и преобразувайте получените дни в Interval Type.
  • След това извлечете часовете, минутите и секундите от интервала.

Забележка: Тази заявка предполага, че и двете дати са в един и същи ден и двете не са преди 10 сутринта или след 19 ч.

АКТУАЛИЗИРАНЕ: За да изключите празниците, заявката ще стане сложна. Предлагам да напишете три функции и да използвате тези функции в заявката.

1-ва функция:

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;

Ако началният час е извън работното време, променете началния час до следващия най-близък начален час.

2-ра функция:

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;

Ако крайното време е извън работното време, променете го до най-близкия предишен край.

3-та функция:

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Прикачени файлове в Oracle Applications R12

  2. 2 начина за връщане на редове, които съдържат само буквено-цифрови знаци в Oracle

  3. Oracle :как да извадите две дати и да получите минути от резултата

  4. какво е oracle EBS R12

  5. Най-добрият начин да нулирате последователност на Oracle до следващата стойност в съществуваща колона?