Oracle 动态 SQL 列

发布于 2024-08-10 19:15:18 字数 616 浏览 2 评论 0原文

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

在这种情况下,我将每天为某个日期范围内的某个代码提取三个值。

假设在该存储过程的某个运行中,我有一个日期范围的代码值 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。

I am writing a stored procedure for which I need to populate a table based on the data being reported on.

In this situation, I will be pulling in three values per day for a certain code in a date range.

Say on a certain run of this stored procedure, I have code values X, Y, and Z for a date range as so:

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'

So for each day in the date range, I have three records for codes x,y, and z.

In my final table, I need to transform this from rows to columns. Normally I would use the decode function, but here I want to create my final table dynamically based on the data coming back.

In this case I would have one record for each day in the range and have 9 more columns (val_1_X, val_2_x, val_3_x, val_1_y, and so on).

I would like to set this up dynamically so that I do not need to re-open my stored procedure when a new "code" is introduced and so that on each instance of the report, only the "codes" being returned on that instance of the report are included on the final table.

Is this possible through dynamic sql? I am on Oracle version 10g.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

洋洋洒洒 2024-08-17 19:15:18

据我了解,2009 年 10 月 1 日到 2009 年 10 月 31 日只有代码 xyz,而一直到 30 -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'''

From my understanding, 01-OCT-2009 to 31-OCT-2009 has only codes x, y and z, while going through to 30-NOV-2009 might also yield you w.

Ultimately, you want a query like this:

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

I'm not an Oracle guy and don't have access to test on Oracle, so you might find quite a few syntax errors and the like below. You'll also need to change the hard coded dates to variables, declare some variables and actually run the created query.

-- 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'''
如梦亦如幻 2024-08-17 19:15:18

非常感谢您的帮助,但事实证明我终究无法走这条路。存储的过程将由报告工具启动和使用,我需要为此报告的多个实例同时运行的可能性做好准备,所以我不能重新使用表名,我不会'不允许有一个存储过程来创建每个运行实例唯一的表。

不过再次感谢您的帮助!

Thanks so much for the help, but it turns out I'm not going to be able to go down this path after all. The stored procdure was to be kicked off and used by a reporting tool, and I need to be prepared for possiblity that multiple instances of this report will be running simultaneously, so I can't be re-using a table name and I won't be allowed to have a stored procedure that creates a table unique to each run instance.

Thanks for the help again though!

笔芯 2024-08-17 19:15:18

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

For mutiple instance use Global temp tables with options on commit delete rows or on commit preserve based on requirement. Irrespective of options records will be available only for that session.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文