0

我需要一些帮助来完成这个过程。问题是如何为不同的 SELECT 设置别名,以便我可以在 RIGHT OUTER JOIN 上匹配它们。传统的 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

是的,我有一些想法。 using 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 回答