Написание функции Oracle для возврата времени события, если оно не в другом событии - PullRequest
1 голос
/ 17 декабря 2010

Позвольте мне объяснить, что я хочу: Есть некоторые компоненты, которые могут выйти из строя по некоторым причинам, и у них есть приоритеты.Теперь я хочу, чтобы, если событие произошло и его приоритет был низким, я передам его время начала и время окончания функции и посмотрю, есть ли какой-то другой высокий приоритеткомпонент, который был там в тот период времени.Если был, то есть четыре случая:

  1. Если событие с низким приоритетом находится во времени события с высоким приоритетом, тогда время равно 0.

  2. Если время окончания события имеет высокий приоритет, но время начала находится за пределами высокого приоритета, то время за пределами события.

  3. Если время начала событияв высоком приоритете, но время окончания выходит за пределы высокого приоритета, а затем время вне события.

  4. и начало, и конец отсутствуют, значит высокий приоритет находится между событием низкого приоритета.

Пример: Предположим, что каждое событие имеет высокий приоритет.Я отправляю время начала и время окончания, например, 12:41:01 и 12:49:01

component  start time  end time  
1          12:40:01    12:50:01   result will be 0 because it's between the start & end
2          12:40:01    12:48:01   result will be 1 minute
3          12:43:01    12:50:01   result will be 2 minutes
4          12:43:01    12:44:01   result will be 7 minutes

Я хочу, чтобы функция вернула мне время в секундах.Мне все время приходится сравнивать его с каждым компонентом, и я не знаю, как это сделать только в функции, а не в процедуре.

Ответы [ 2 ]

2 голосов
/ 17 декабря 2010

С учетом следующего определения таблицы

CREATE TABLE EVENT_OCCURRENCE
  (COMPONENT        NUMBER PRIMARY KEY,
   PRIORITY         VARCHAR2(6) NOT NULL
     CHECK(PRIORITY IN ('HIGH', 'MEDIUM', 'LOW')),
   START_TIME       DATE NOT NULL,
   END_TIME         DATE NOT NULL);

со следующими данными

INSERT INTO EVENT_OCCURRENCE (COMPONENT, PRIORITY, START_TIME, END_TIME)
  VALUES (1, 'HIGH', TRUNC(SYSDATE) + INTERVAL '0 12:40:01' DAY TO SECOND, TRUNC(SYSDATE) + INTERVAL '0 12:50:01' DAY TO SECOND);

INSERT INTO EVENT_OCCURRENCE (COMPONENT, PRIORITY, START_TIME, END_TIME)
  VALUES (2, 'HIGH', TRUNC(SYSDATE) + INTERVAL '0 12:45:01' DAY TO SECOND, TRUNC(SYSDATE) + INTERVAL '0 12:48:01' DAY TO SECOND);

INSERT INTO EVENT_OCCURRENCE (COMPONENT, PRIORITY, START_TIME, END_TIME)
  VALUES (3, 'HIGH', TRUNC(SYSDATE) + INTERVAL '0 12:39:01' DAY TO SECOND, TRUNC(SYSDATE) + INTERVAL '0 12:46:01' DAY TO SECOND);

INSERT INTO EVENT_OCCURRENCE (COMPONENT, PRIORITY, START_TIME, END_TIME)
  VALUES (4, 'HIGH', TRUNC(SYSDATE) + INTERVAL '0 12:38:01' DAY TO SECOND, TRUNC(SYSDATE) + INTERVAL '0 12:55:01' DAY TO SECOND);

следующая процедура НЕ даст результатов, о которых вы просили, но, учитывая, что в вашем объяснении не хватает подробностей, я думаю, это лучшее, на что вы можете надеяться. Это должно дать вам что-то, с чего можно начать, чтобы получить то, что вы думаете:

CREATE OR REPLACE PROCEDURE PRINT_INTERSECTING_OCCURRENCES(dtEvent_start IN DATE,
                                                           dtEvent_end IN DATE) IS
BEGIN
  DBMS_OUTPUT.PUT_LINE('dtEvent_start=' || TO_CHAR(dtEvent_start, 'DD-MON-YYYY HH24:MI:SS') ||
                       '   dtEvent_end=' || TO_CHAR(dtEvent_end, 'DD-MON-YYYY HH24:MI:SS'));

  FOR aRow IN (SELECT E.*,
                      CASE
                        WHEN dtEvent_start >= E.START_TIME 
                             AND dtEvent_end <= E.END_TIME 
                        THEN
                          0
                        WHEN dtEvent_start <  E.START_TIME
                            AND dtEvent_end BETWEEN E.START_TIME AND E.END_TIME 
                        THEN
                          (E.START_TIME - dtEvent_start) * (24 * 60 * 60)
                        WHEN dtEvent_start BETWEEN E.START_TIME AND E.END_TIME 
                             AND dtEvent_end > E.END_TIME 
                       THEN
                          (dtEvent_end - E.END_TIME) * (24 * 60 * 60)
                    WHEN dtEvent_start >  E.END_TIME
                        OR dtEvent_end < E.START_TIME  
                    THEN
                         (dtEvent_end - dtEvent_start) * (24 * 60 * 60)
                    ELSE
                          ((E.START_TIME - dtEvent_start) * (24 * 60 * 60))
                             + ((dtEvent_end - E.END_TIME) * (24 * 60 * 60))
                      END AS TIME_DIFF
                 FROM EVENT_OCCURRENCE E
                 WHERE E.PRIORITY = 'HIGH')
  LOOP
    DBMS_OUTPUT.PUT_LINE('COMPONENT=' || aRow.COMPONENT ||
                         '  PRIORITY=' || aRow.PRIORITY ||
                         '  START_TIME=' || TO_CHAR(aRow.START_TIME, 'DD-MON-YYYY HH24:MI:SS') ||
                         '  END_TIME=' || TO_CHAR(aRow.END_TIME, 'DD-MON-YYYY HH24:MI:SS') ||
                         '  TIME_DIFF=' || aRow.TIME_DIFF);
  END LOOP;
END PRINT_INTERSECTING_OCCURRENCES;

Делись и наслаждайся.

0 голосов
/ 17 декабря 2010

Описание, кажется, не имеет смысла, но я думаю, что это то, что вы могли бы искать (предполагая, что start_time_in и end_time_in являются именами ваших входных переменных).

select component, ((start_time - least(start_time, start_time_in)) + (greatest(end_time, end_time_in) - end_time)) * 24*60*60 seconds_outside_window   
from table
...