[英]Dynamic column creation with Oracle SQL
目前我正在研究固定资产注册报告棒,我需要在主查询中添加Projection
列。
Depreciation Remaining Life of
Assed_No Amount asset in months
-------- ------------ -----------------
1 400 6
2 200 3
3 100 4
4 600 1
现在,我想在SQL中进行修改,根据月份列中资产的剩余寿命应该生成。 对于第一个资产,资产的剩余寿命为6个月,因此总共6个投影列的值应为400.如果剩余寿命小于最大值。 即6然后它应该为其余列提供0。
我想要如下的最终解决方案,
Depreciation Remaining Life of
Assed_No Amount asset in months Projection 1 Projection 2 Projection 3 Projection 4 Projection 5 Projection 6
-------- ------------ ----------------- ------------ ------------ ------------ ------------ ------------ ------------
1 400 6 400 400 400 400 400 400
2 200 3 200 200 0 0 0 0
3 100 4 100 100 100 100 0 0
4 600 1 600 0 0 0 0 0
您可以为每个投影使用简单的大小写表达式:
-- CTE for sample data
with your_table (asset_no, amount, remaining_months) as (
select 1, 400, 6 from dual
union all select 2, 200, 3 from dual
union all select 3, 100, 4 from dual
union all select 4, 600, 1 from dual
)
-- query using my CTE column names
select asset_no, amount, remaining_months,
case when remaining_months >= 1 then amount else 0 end as proj_1,
case when remaining_months >= 2 then amount else 0 end as proj_2,
case when remaining_months >= 3 then amount else 0 end as proj_3,
case when remaining_months >= 4 then amount else 0 end as proj_4,
case when remaining_months >= 5 then amount else 0 end as proj_5,
case when remaining_months >= 6 then amount else 0 end as proj_6
from your_table;
ASSET_NO AMOUNT REMAINING_MONTHS PROJ_1 PROJ_2 PROJ_3 PROJ_4 PROJ_5 PROJ_6
---------- ---------- ---------------- ---------- ---------- ---------- ---------- ---------- ----------
1 400 6 400 400 400 400 400 400
2 200 3 200 200 200 0 0 0
3 100 4 100 100 100 100 0 0
4 600 1 600 0 0 0 0 0
这基本上是Alex查询的动态版本(作为奖励!)
注意使用refcursor Bind变量。 当您在SQl * Plus中运行它或在SQL开发人员或Toad中作为脚本(F5)运行时,这将起作用。
您也可以在Oracle 12c及更高版本中使用DBMS_SQL.RETURN_RESULT
来执行相同的操作。
VARIABLE x REFCURSOR;
DECLARE
v_case_expr VARCHAR2(1000);
BEGIN
SELECT
listagg('CASE WHEN remaining_months > = '
|| level
|| '
then amount else 0 end as proj_'
|| level,',') WITHIN GROUP ( ORDER BY level)
INTO v_case_expr
FROM
dual
CONNECT BY
level <= (
SELECT
MAX(remaining_months)
FROM
assets
);
OPEN :x FOR 'select asset_no, amount, remaining_months, '
|| v_case_expr
|| ' FROM assets';END;
/
PRINT x;
PL/SQL procedure successfully completed.
ASSET_NO AMOUNT REMAINING_MONTHS PROJ_1 PROJ_2 PROJ_3 PROJ_4 PROJ_5 PROJ_6
---------- ---------- ---------------- ---------- ---------- ---------- ---------- ---------- ----------
1 400 6 400 400 400 400 400 400
2 200 3 200 200 200 0 0 0
3 100 4 100 100 100 100 0 0
4 600 1 600 0 0 0 0 0
当计算量增加时,有时枢轴可能会更好。 这里我之前使用笛卡尔积来创建数据:
with dat (asset_no, dep_amount, r_life)as
( select 1, 400, 6 from dual union all
select 2, 200, 3 from dual union all
select 3, 100, 4 from dual union all
select 4, 600, 1 from dual )
, mon as (select level lv from dual connect by level <= 6)
, bas as (
select asset_no, dep_amount, r_life, lv, case when r_life >= lv then dep_amount else 0 end proj_m from dat, mon)
select *
from bas
pivot(sum(proj_m) for lv in (1 as proj_1,2 as proj_2,3 as proj_3,4 as proj_4,5 as proj_5,6 as proj_6))
order by asset_no
认为带有案例表达的解决方案在这里更好
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.