【发布时间】:2020-12-15 05:51:12
【问题描述】:
我正在构建一个报告,该报告应根据请求的年份(即 2000 年到 2002 年)生成动态列列表。用户应该能够通过 SELECT 语句运行报告,如下所示:
SELECT * FROM TABLE(myreport(2002, 3)); -- Get 3 report years starting with 2002
目前,我有一个生成此输出的表函数,但具有静态列名:
-- Row type
CREATE OR REPLACE TYPE typ_myreport AS OBJECT (
myuser VARCHAR(260),
yr1_p DECIMAL(5,2),
yr1_t INTEGER,
yr2_p DECIMAL(5,2),
yr2_t INTEGER,
...
);
-- Table type
CREATE OR REPLACE TYPE tab_myreport AS TABLE OF typ_myreport;
-- Report
CREATE OR REPLACE FUNCTION myreport(pAsOfYear IN INTEGER)
RETURN tab_myreport PIPELINED AS
BEGIN
FOR vRec IN (
SELECT user_name, yr1_p, yr1_t, y2_p, y2_t, ...
FROM mytable
)
LOOP
PIPE ROW (
typ_myreport(vRec.user_name, vRec.yr1_p, vRec.yr1_t, vRec.yr2_p, vRec.year2_t, ...)
);
END LOOP;
RETURN;
END;
它产生这样的输出:
User yr1_p yr1_t yr2_p yr2_t yr3_p yr3_t
-----------------------------------------------------
Bobby 25 2 33 2 20 4
Barry 50 4 66 4 50 10
Big Ben 25 2 0 0 30 6
但我希望根据请求的年份动态命名列:
User 2000_p 2000_t 2001_p 2001_t 2002_p 2002_t
------------------------------------------------------
Bobby 25 2 33 2 20 4
Barry 50 4 66 4 50 10
Big Ben 25 2 0 0 30 6
输出结果集应该保持完全相同——表结构、数据类型——只是列名应该改变。我的想法是通过动态构建的SELECT 语句来执行此操作,我可以执行该语句然后返回结果。我摸索着试图让它工作,但没有运气。
有没有办法在具有动态列数和列名的函数/过程中编写动态 SQL,然后将该结果集作为 表(不是脚本)输出?
更新
这是生成 yr 字段的实际查询的简化 sn-p:
WITH rpt_years AS (SELECT * FROM TABLE(GetReportyears(pAsOfYear)))
SELECT user_name,
SUM(year1_cnt) AS yr1_t,
SUM(COALESCE((year1_cnt / NULLIF(year1_tot,0)),0)) AS yr1_p,
SUM(year2_cnt) AS yr2_t,
SUM(COALESCE((year2_cnt / NULLIF(year2_tot,0)),0)) AS yr2_p,
...
FROM (
SELECT DISTINCT
ui.user_name,
SUM(CASE WHEN s.dist_year = y.year1 THEN 1 END) AS year1_cnt,
COUNT(CASE WHEN s.dist_year = y.year1 THEN 1 END) AS year1_tot,
SUM(CASE WHEN s.dist_year = y.year2 THEN 1 END) AS year2_cnt,
COUNT(CASE WHEN s.dist_year = y.year2 THEN 1 END) AS year2_tot,
...
FROM rpt_years y -- Get report years as single row
INNER JOIN src_table s
...
) src
ORDER BY src.user_name
【问题讨论】:
-
我真的不知道为什么不在
select语句中使用别名,而是尝试在您的函数中添加alter table? -
什么程序会运行报告?如果它是一个理解 ref cursors 的应用程序,您可以创建一个返回动态生成的 sys_refcursor 的函数。
-
开发人员需要运行内部报告,因此 IntelliJ 或 Eclipse 的内置 SQL 编辑器或可能是 Oracle SQL Developer。
-
@ravioli 这可以做到,但你的表结构到底是什么?该表是否已经包含名称如 yr1_p、yr1_t 且始终与年份一致的列,或者这些列是否真的从其他来源聚合或转置?
标签: oracle dynamic-sql dynamic-columns table-functions