首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Oracle中组合结果集?

如何在Oracle中组合结果集?
EN

Stack Overflow用户
提问于 2011-06-03 22:55:18
回答 4查看 3.8K关注 0票数 3

我有一个具有in参数和out游标的过程。该光标给出的结果如下所示:

代码语言:javascript
运行
复制
0100 | 0
0130 | 1
0200 | 2
0230 | 0
...

第一列是静态时间代码。第二列是在给定的一天中,某件事情在该时间段内被调度的次数的汇总。

该过程为:

代码语言:javascript
运行
复制
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,并按第一列对每个分组的第一列和第二列进行分组。

现在,我有像这样的东西

代码语言:javascript
运行
复制
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中做到这一点?Fetch with bulk collect看起来很有前途,但我没有看到在我的特定场景中使用它的好方法。

EN

回答 4

Stack Overflow用户

发布于 2011-06-03 23:40:39

您可以作为一个联合来执行此操作,包括一个标识组的列。单个选择将或多或少地复制您的DailyLoad SP正在执行的操作。

代码语言:javascript
运行
复制
 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语句对临时表发出group。

票数 0
EN

Stack Overflow用户

发布于 2011-06-04 00:01:18

如果该过程的out参数是一个引用游标,并且您不能像OMG Ponies建议的那样在内部复制它所做的工作来生成一个很好的基于集合的查询,那么this previous answer可能会有所帮助。您可以使用中间流水线函数将sys_refcursor结果转换为可以作为表处理的内容:

代码语言:javascript
运行
复制
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;
/

猜测您的数据类型,并从一个随机表中挑选数据,就像crouse的例子一样。要从SQL*Plus或SQL Developer调用:

代码语言:javascript
运行
复制
var results refcursor;

exec p.sumload(to_date('01-Jun-11','DD-Mon-RR'), :results);

print :results
票数 0
EN

Stack Overflow用户

发布于 2011-06-04 01:11:10

我没有时间来测试它,但我相信它会起作用的:

  1. 修改存储过程,使SYS_REFCURSOR成为in OUT参数,而不仅仅是OUT参数。
  2. 在for/each循环中设置参数(无论您使用的是哪种语言...)循环中的
  3. 传入对同一sproc的引用sproc创建一个本地SYS_REFCURSOR变量,以便像您当前所做的那样进行选择。sproc中的
  4. 合并local和参数OUT

这应该会构建您的结果集。

如果您不想对此进行测试,我可能会在周末用C#/Oracle10g为此构建一个测试用例,以验证我的假设。

如果你使用的是11g,另一种选择是流水线查询,就像讨论的How to create Oracle stored procedure which can return specific entities as well all entity一样(看看@tbone的答案和他提供的链接……)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6228739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档