我有一个具有in参数和out游标的过程。该光标给出的结果如下:
0100 | 0
0130 | 1
0200 | 2
0230 | 0
...
第一列是静态时间码。第二列是在给定日期在该时间段内安排了多少次事件的聚合。
该程序是:
PROCEDURE DAILYLOAD (datep IN DATE, results OUT SYS_REFCURSOR)
AS
BEGIN
Open results for
SELECT RUN_TIME_C, COUNT (SCH_RPT_I)
FROM ITS_SCH_RPT_RUN_TIME
LEFT OUTER JOIN
ITS_SCH_RPT
ON ( RUN_TIME_C = RUN_TIME1_C
OR RUN_TIME_C = RUN_TIME2_C
OR RUN_TIME_C = RUN_TIME3_C)
WHERE EXP_DATE_D IS NULL
OR datep < exp_date_d AND datep > start_date_d AND SUSPENDED_USER='N'
AND ( ( (TO_CHAR (datep, 'D') = 1) AND RUN_SUNDAY_C = 'Y')
OR ( (TO_CHAR (datep, 'D') = 2) AND RUN_MONDAY_C = 'Y')
OR ( (TO_CHAR (datep, 'D') = 3) AND RUN_TUESDAY_C = 'Y')
OR ( (TO_CHAR (datep, 'D') = 4) AND RUN_WEDNESDAY_C = 'Y')
OR ( (TO_CHAR (datep, 'D') = 5) AND RUN_THURSDAY_C = 'Y')
OR ( (TO_CHAR (datep, 'D') = 6) AND RUN_FRIDAY_C = 'Y')
OR ( (TO_CHAR (datep, 'D') = 7) AND RUN_SATURDAY_C = 'Y'))
GROUP BY RUN_TIME_C
ORDER BY RUN_TIME_C;
END DAILYLOAD;
我想使用不同的参数从包装过程中多次调用此过程,以便我可以提出每周加载和每月加载。从概念上讲,这可以通过连接各个结果集来完成,例如union all,并将第一列的每个结果组合在一起,对第一列进行分组。
现在,我有类似
的东西Dailyload(datep, results1);
Dailyload(datep + 1, results2);
...
OPEN results FOR
SELECT run_time_c,
SUM(rpt_option_i)
FROM SELECT *
FROM results1
UNION ALL
SELECT *
FROM results2
UNION ALL ...
GROUP BY run_time_c
ORDER BY run_time_c
我有办法在Oracle中做到这一点吗?使用批量收集进行抓取看起来很有希望,但我没有看到在我的特定场景中使用它的好方法。
答案 0 :(得分:0)
您可以将此作为联合执行,包括标识该组的列。个人选择会或多或少地复制DailyLoad SP正在做的事情。
select foo.Mygroup, sum(foo.col1)
from
(
select 'A' as MyGroup, col1 WHERE ...
union all
select 'B' as MyGroup, col1 WHERE ...
union all
select 'C' as MyGroup, col1 WHERE ...
) as Foo
group by MyGroup
如果事先不知道组的数量,您可以构建一个符合此基本结构的动态sql语句。
如果组的数量太大而动态语句太大,则可以使用存储过程将每次调用的结果与MyGroup列一起推送到临时表中。然后,您可以通过针对临时表的select语句发出组。
答案 1 :(得分:0)
如果过程的out参数是引用游标,并且你无法复制它在内部做的事情,以便像OMG Ponies所建议的那样建立一个很好的基于单集的查询,this previous answer可能有所帮助。您可以使用中间管道化函数将sys_refcursor结果转换为可以视为表的内容:
create package p as
type tmp_rec_type is record (run_time_c varchar2(4),
rpt_option_i number);
type tmp_table_type is table of tmp_rec_type;
procedure dailyload(p_date in date, p_results out sys_refcursor);
function func(p_date in date) return tmp_table_type pipelined;
procedure sumload(p_start_date in date, p_results out sys_refcursor);
end;
/
create package body p as
/* Your existing procedure, which may be elsewhere */
procedure dailyload(p_date in date, p_results out sys_refcursor) is
begin
open p_results for
select to_char(created, 'HH24MI') as run_time_c,
count(*) as rpt_option_i
from all_objects
where trunc(created) = trunc(p_date)
group by to_char(created, 'HH24MI');
end;
/* Intermediate pipelined function */
function func(p_date in date) return tmp_table_type pipelined is
tmp_cursor sys_refcursor;
tmp_rec tmp_rec_type;
begin
dailyload(p_date, tmp_cursor);
loop
fetch tmp_cursor into tmp_rec;
exit when tmp_cursor%notfound;
pipe row(tmp_rec);
end loop;
end;
/* Wrapper function to join the result sets together */
procedure sumload(p_start_date in date, p_results out sys_refcursor) is
begin
open p_results for
select run_time_c, sum(rpt_option_i) from (
select * from table(func(p_start_date))
union all
select * from table(func(p_start_date + 1))
union all
select * from table(func(p_start_date + 2))
)
group by run_time_c;
end;
end;
/
猜测您的数据类型,并从随机表中选择数据作为例子。从SQL * Plus或SQL Developer调用:
var results refcursor;
exec p.sumload(to_date('01-Jun-11','DD-Mon-RR'), :results);
print :results
答案 2 :(得分:0)
我没有时间对此进行测试,但我相信这会有效:
这应该构建您的结果集。
如果您不想对此进行测试,我可以在周末为C#/ Oracle 10g构建一个测试用例,以测试我的假设。
另一个选项,如果你是11g,将是一个如所讨论How to create Oracle stored procedure which can return specific entities as well all entity的流水线查询(看看@tbone的回答和他提供的链接......)
答案 3 :(得分:0)
您可以使用oracle全局临时表来累积和进一步处理数据。
它是内存中的结构,开销很小。