0

この手順を完了するのに助けが必要です。問題は、RIGHT OUTER JOIN でそれらを一致させることができるように、さまざまな SELECT に別名を付ける方法です。従来の AS は機能しません。何か案は?

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";
4

3 に答える 3

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 
于 2013-02-05T12:43:41.323 に答える
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";
于 2013-02-05T10:42:58.553 に答える
0

構文で必要な場合を除き、変数名を囲む二重引用符を削除してみてください。それはパーサーを混乱させる可能性があります。

于 2013-02-05T11:53:42.073 に答える