我正在编写一个存储过程,我需要根据报告的数据填充表。
在这种情况下,我会在日期范围内为某个代码每天提取三个值。
假设在这个存储过程的某个运行中,我有一个日期范围的代码值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的记录。
在我的决赛桌中,我需要将其从行转换为列。通常我会使用解码函数,但在这里我想根据返回的数据动态创建我的最终表。
在这种情况下,我会在该范围内的每一天有一条记录,并且还有9列(val_1_X,val_2_x,val_3_x,val_1_y等)。
我想动态设置它,以便在引入新的“代码”时不需要重新打开我的存储过程,因此在报表的每个实例上只返回“代码”该报告的实例包含在决赛桌上。
这可以通过动态sql实现吗?我使用的是Oracle 10g版本。
答案 0 :(得分:1)
根据我的理解,01-OCT-2009至31-OCT-2009只有代码 x , y 和 z 到31-NOV-2009也可能会让你 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'''
答案 1 :(得分:0)
非常感谢你的帮助,但事实证明,毕竟我不能走这条路。存储的程序将被启动并由报告工具使用,我需要做好准备,以便同时运行此报告的多个实例,因此我不能重复使用表名,我赢了允许有一个存储过程创建一个对每个运行实例唯一的表。
再次感谢您的帮助!
答案 2 :(得分:0)
对于多个实例,使用全局临时表,其中包含基于需求的提交删除行或提交保留的选项。无论选项记录是否仅适用于该会话。