2013-02-05 5 views
0

Мне нужна помощь в завершении этой процедуры. Проблема заключается в том, как использовать псевдонимы для разных SELECT, чтобы я мог сопоставлять их с RIGHT OUTER JOIN. Традиционная АС не работает. Есть идеи?Oracle Procedure - JOIN with Subquery

PROCEDURE "GetProcessedEvents" 
(
"In_OccurredFrom" TIMESTAMP, 
"In_OccurredTo" TIMESTAMP, 
"In_Interval" DECIMAL, 
"Out_Cursor" OUT "Ref_Cursor" 
) 
IS 
BEGIN  
OPEN "Out_Cursor" FOR  
    SELECT 
    COUNT("Id") AS "ProcessedEvents", 
    TO_TIMESTAMP('1900-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.FF') + NUMTODSINTERVAL(FLOOR(DATEDIFF('MI', '1900-01-01', "ProcessedDate")/"In_Interval")*"In_Interval", 'MINUTE') AS "EventDts" 
    FROM "Dat_ScheduledEvent" 
    RIGHT OUTER JOIN 
    (SELECT "Dts" FROM TABLE("F_GetDateIntervalTable"("In_OccurredTo", "In_OccurredFrom", "In_Interval"))) 
    ON "EventDts" = "Dts" 
    WHERE 
    "ProcessedDate" BETWEEN "In_OccurredFrom" AND "In_OccurredTo" 
    GROUP BY 
    TO_TIMESTAMP('1900-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.FF') + NUMTODSINTERVAL(FLOOR(DATEDIFF('MI', '1900-01-01', "ProcessedDate")/"In_Interval")*"In_Interval", 'MINUTE'); 
END "GetProcessedEvents"; 
+0

Что вы имеете в виду, когда говорите, что он не работает? Что не работает? Вы получаете неправильные данные или это просто не работает? Возможно, описание того, что он должен делать, может помочь. Все это malarkey с «In_interval» немного сложно понять. –

ответ

1

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

FROM "Dat_ScheduledEvent" alias1 
    RIGHT OUTER JOIN (
    SELECT "Dts" 
    FROM TABLE("F_GetDateIntervalTable"("In_OccurredTo", "In_OccurredFrom", 
     "In_Interval")) 
) alias2 

Но у вас есть какие-то другие проблемы. Во-первых, создание объектов с идентификаторами, которые должны быть заключены в двойные кавычки, болезненно для работы; имеет ли идентификатор смешанного случая действительно стоит? Во-вторых, похоже, что EventDts - это только производное поле, а псевдоним столбца не может использоваться нигде в запросе, отличном от предложения order by, поэтому вам, вероятно, также потребуется сделать этот подзапрос, что означает, что вы можете использовать его в group by тоже. В-третьих, DATEDIFF не является встроенной функцией Oracle - если вы не создали ее самостоятельно, вам нужно будет использовать что-то еще.

SELECT 
    COUNT(alias1."Id") AS "ProcessedEvents", 
    alias1."EventDts"   
    FROM (
    SELECT "Id", 
     TO_TIMESTAMP('1900-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.FF') 
     + NUMTODSINTERVAL(FLOOR(DATEDIFF('MI', '1900-01-01', "ProcessedDate") 
      /"In_Interval")*"In_Interval", 'MINUTE') AS "EventDts" 
    FROM "Dat_ScheduledEvent" 
    WHERE "ProcessedDate" BETWEEN "In_OccurredFrom" AND "In_OccurredTo" 
) alias1 
    RIGHT OUTER JOIN (
    SELECT "Dts" 
    FROM TABLE("F_GetDateIntervalTable"("In_OccurredTo", "In_OccurredFrom", 
     "In_Interval")) 
) alias2 
    ON alias1."EventDts" = alias2."Dts" 
    GROUP BY alias2."EventDts"; 

DATEDIFF все еще нуждается в замене, но я не совсем уверен, что вы делаете. Если F_GetDateIntervalTable генерирует подходящие интервалы, я не уверен, зачем вам это нужно; вы не хотите находить ProcessedDate значений в пределах интервалов, то есть >= Dt and < Dt + InInterval? В зависимости от того, что на самом деле представляет InInterval, конечно.


Предполагая, что F_GetDateIntervalTable дает начало каждого интервала в период интереса, вы можете сделать что-то вроде этого, вместо:

PROCEDURE "GetProcessedEvents" 
(
"In_OccurredFrom" TIMESTAMP, 
"In_OccurredTo" TIMESTAMP, 
"In_Interval" DECIMAL, 
"Out_Cursor" OUT "Ref_Cursor" 
) 
IS 
BEGIN  
OPEN "Out_Cursor" FOR 
    SELECT 
    COUNT(Event."Id") AS "ProcessedEvents", 
    DateInt."Dts" 
    FROM (
    SELECT "Dts", COALESCE(LEAD("Dts") 
     OVER (ORDER BY "Dts"), "In_OccurredTo") as "NextDts" 
    FROM TABLE("F_GetDateIntervalTable"("In_OccurredTo", "In_OccurredFrom", 
     "In_Interval")) 
) DateInt 
    LEFT JOIN "Dat_ScheduledEvent" Event 
    ON Event."ProcessedDate" >= DateInt."Dts" 
    AND Event."ProcessedDate" < DateInt."NextDts" 
    GROUP BY DateInt."Dts" 
    ORDER BY DateInt."Dts"; 
END "GetProcessedEvents"; 
/

LEAD() позволяет заглянуть в следующий результат, так что подзапрос преобразует список временных меток в список из временных и временных меток (с последним заканчивается на In_OccurredTo), что позволяет искать соответствующие записи в вашей таблице данных, которые попадают в эти диапазоны - никакие манипуляции с ProcessedDate не являются необходимо.

С некоторыми поддельные данные:

create table "Dat_ScheduledEvent" ("Id" number, "ProcessedDate" timestamp); 

insert into "Dat_ScheduledEvent" ("Id", "ProcessedDate") 
    values (1, to_timestamp('2013-02-06 09:45', 'YYYY-MM-DD HH24:MI')); 
insert into "Dat_ScheduledEvent" ("Id", "ProcessedDate") 
    values (1, to_timestamp('2013-02-06 09:50', 'YYYY-MM-DD HH24:MI')); 
insert into "Dat_ScheduledEvent" ("Id", "ProcessedDate") 
    values (1, to_timestamp('2013-02-06 10:15', 'YYYY-MM-DD HH24:MI')); 

... и вызова процедуры из SQL * Plus:

var r refcursor; 
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI'; 
exec "GetProcessedEvents"(to_date('2013-02-06 08:00'), to_date('2013-02-06 12:00'), 1/24, :r); 
print :r 

...Я получаю:

ProcessedEvents  Dts      
---------------------- ------------------------- 
0      06-FEB-13 08.00.00.000000000 
2      06-FEB-13 09.00.00.000000000 
1      06-FEB-13 10.00.00.000000000 
0      06-FEB-13 11.00.00.000000000 
+0

Отлично, я попробую! – user902264

+0

F_GetDateIntervalTable получает все TimeStamps, некоторые из которых могут отсутствовать в наборе статистики I ' м при получении. Так вместо того, чтобы 2013-01-01 00:00 100 2013-01-01 02:00 130 я 2013-01-01 00:00 100 2013-01-01 01:00 0 2013-01-01 02:00 130 И да, я добавил DATEDIFF в качестве локальной функции. (Я пришел из MSSQL) – user902264

+0

Спасибо! так и не давал мне такую ​​головную боль с бесчисленным количеством потраченных впустую часов, пытаясь с этим поиграть. Единственные изменения, которые я сделал с этим, заключались в удалении множества событий, которые не нужны, и переключили места на From и To в части COALESCE. – user902264

0

Да, у меня есть идеи. Может быть полезно использоватьWITH, что позволяет разбивать сложные операторы SELECT на подзапросы, которые существенно улучшают структуру вашего кода и, конечно же, вы можете ссылаться на них (подзапросы) на псевдоним.

Вот небольшой пример использования для вас:

WITH subquery AS (SELECT sysdate FROM dual) 
-- Here goes main query where subquery must be used 
SELECT * 
FROM subquery 


OPEN "Out_Cursor" FOR  
WITH Q AS (SELECT "Dts" FROM TABLE("F_GetDateIntervalTable"("In_OccurredTo", "In_OccurredFrom", "In_Interval"))) 

SELECT 
    COUNT("Id") AS "ProcessedEvents", 
    TO_TIMESTAMP('1900-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.FF') + NUMTODSINTERVAL(FLOOR(DATEDIFF('MI', '1900-01-01', "ProcessedDate")/"In_Interval")*"In_Interval", 'MINUTE') AS "EventDts" 
    FROM "Dat_ScheduledEvent" 
    RIGHT OUTER JOIN 
    Q 
    ON "EventDts" = "Dts" 
    WHERE 
    "ProcessedDate" BETWEEN "In_OccurredFrom" AND "In_OccurredTo" 
    GROUP BY 
    TO_TIMESTAMP('1900-01-01 00:00:00.000000', 'YYYY-MM-DD HH24:MI:SS.FF') + NUMTODSINTERVAL(FLOOR(DATEDIFF('MI', '1900-01-01', "ProcessedDate")/"In_Interval")*"In_Interval", 'MINUTE'); 
END "GetProcessedEvents"; 
+0

Я пытался использовать WITH, но где его поместить в ПРОЦЕДУРУ без его нытья? Я попытался положить его 'ПРОЦЕДУРА КАК С BEGIN' ' НАЧАТЬ С OPEN' 'ОТКРЫТО ДЛЯ С SELECT' ни один из них не работает, к сожалению :(. – user902264

+0

I Не пробовал, но я мог догадаться: после FOR или до OPEN –

+0

Ошибка (14,7): PLS-00103: При знакомстве с одним из следующих символов встречается символ «WITH»:. (%; для – user902264

0

Попробуйте удалить двойные кавычки имена переменных, если они не требуются по синтаксису. Это может смутить парсер.

+0

EventDts по-прежнему является недопустимым идентификатором – user902264