用于列的Oracle动态SQL

用于列的Oracle动态SQL,sql,oracle,plsql,oracle10g,dynamic-sql,Sql,Oracle,Plsql,Oracle10g,Dynamic Sql,我正在编写一个存储过程,需要根据报告的数据填充一个表 在这种情况下,对于日期范围内的特定代码,我将每天输入三个值 假设在这个存储过程的某次运行中,我有一个日期范围的代码值X、Y和Z,如下所示: select abc.code, abc.date, abc.val_1, abc.val_2, abc.val_3 from data.abc where abc.date BETWEEN '01-OCT-2009' AND '31-

我正在编写一个存储过程,需要根据报告的数据填充一个表

在这种情况下,对于日期范围内的特定代码,我将每天输入三个值

假设在这个存储过程的某次运行中,我有一个日期范围的代码值X、Y和Z,如下所示:

select abc.code, 
       abc.date, 
       abc.val_1, 
       abc.val_2, 
       abc.val_3
  from data.abc
 where abc.date BETWEEN '01-OCT-2009' AND '31-OCT-2009'
因此,对于日期范围内的每一天,我有三条代码x、y和z的记录

在最后一个表中,我需要将其从行转换为列。通常我会使用decode函数,但这里我想根据返回的数据动态创建最终表

在本例中,该范围内每天有一条记录,并有9个以上的列(val_1_X、val_2_X、val_3_X、val_1_y,等等)

我希望动态地设置它,以便在引入新的“代码”时不需要重新打开存储过程,并且在报表的每个实例上,只有在该报表实例上返回的“代码”才会包含在最终表中


这可以通过动态sql实现吗?我使用的是Oracle版本10g。

据我所知,2009年10月1日至2009年10月31日只有代码x、y和z,而到2009年11月30日可能也会产生w

最终,您需要这样一个查询:

CREATE TABLE t1 AS
  SELECT
    abc.date,
    MAX(DECODE(code, 'x', val_1, NULL)) AS abc_val_1_x,
    MAX(DECODE(code, 'x', val_2, NULL)) AS abc_val_2_x,
    MAX(DECODE(code, 'x', val_3, NULL)) AS abc_val_3_x,
    MAX(DECODE(code, 'y', val_1, NULL)) AS abc_val_1_y,
    MAX(DECODE(code, 'y', val_2, NULL)) AS abc_val_2_y,
    MAX(DECODE(code, 'y', val_3, NULL)) AS abc_val_3_y,
    ...
  FROM data.abc
  WHERE abc.date BETWEEN '01-OCT-2009' AND '31-OCT-2009'
  GROUP BY abc.date
我不是Oracle的人,也没有在Oracle上进行测试的权限,所以您可能会发现相当多的语法错误和类似的错误。您还需要将硬编码日期更改为变量,声明一些变量并实际运行创建的查询

-- Figure out all valid codes for date range.
-- Might also require ordering depending on your report.
CURSOR c1
  IS
    SELECT
      abc.code
    FROM data.abc
    WHERE abc.date BETWEEN '01-OCT-2009' AND '31-OCT-2009'
    GROUP BY abc.code;

query1 := 'CREATE TABLE abc_report AS SELECT date';
LOOP
    FETCH c1 INTO code1
    EXIT WHEN c1%NOTFOUND;
    query1 := query1 || ', DECODE(code, ''' || code1 || ''', val_1, NULL)) AS abc_val_1_' || code1 ||
        ', DECODE(code, ''' || code1 || ''', val_2, NULL)) AS abc_val_2_' || code1 ||
        ', DECODE(code, ''' || code1 || ''', val_3, NULL)) AS abc_val_3_' || code1
END LOOP;
query1 := query1 || ' FROM data.abc WHERE date BETWEEN ''01-OCT-2009'' AND ''31-OCT-2009'''

非常感谢你的帮助,但事实证明我终究不能走这条路。存储过程将由报表工具启动并使用,我需要准备好此报表的多个实例将同时运行的可能性,因此我不能重复使用表名,也不允许有一个存储过程为每个运行实例创建唯一的表


再次感谢你的帮助

对于多实例,使用全局临时表,并根据需要选择提交删除行或提交保留。无论选项如何,记录仅适用于该会话。

Hi will!欢迎来到StackOverflow!这是对lins314159回答的回应吗?StackOverflow仅通知用户对其答案的评论。除非他再次访问这个问题,否则他不会知道你做出了这个决定。同样,lins314159的答案真的解决了最初的问题吗?如果是这样,你可以考虑接受他的回答来换取他的努力。稍后!:)我建议让报表工具执行任何交叉表/多维数据集/透视,只需担心查询返回正确的数据来支持它。