暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 需要在报表中创建动态列

askTom 2018-07-26
445

问题描述

嗨,汤姆,

我是SQL和PLSQL的新手,我需要创建一个报告,其中包括基于程序持续时间的月数的月动态列。

我实际上尝试在LiveSQL中创建脚本,但是现在它无法访问,因此我提供了所有准备运行的示例脚本。

Create table program_det (program_name varchar2(50), program_date NUMBER);
/

Insert into program_det values('PROGRAM_1', 201801);
Insert into program_det values('PROGRAM_1', 201807);
COMMIT;
/


-
我的确切意思是

我有列 <程序名称> 、 <程序日期>

假设我有一个程序的持续时间为6个月,例如从201801到201806,该月的总数为6。在这种情况下,我需要在报告中动态生成6列,如下所示。

Program_Name Program_Date Month_1 Month_2 Month_3 Month_4 Month_5 Month_6
Program_1 12018  0 0 0 0 0
Program_1 62018  0 0 0 0 0


-
我尝试使用以下方法,在这里我可以找到月数,但我需要帮助基于此月数创建动态列。

select program_name, 
      months_between(TO_DATE(max(program_date),'YYYYMM'),TO_DATE(min(program_date),'YYYYMM')) 
       number_months
from program_det
where program_name ='PROGRAM_1'
group by program_name;

-

我不确定,如果这可能是非常愚蠢和简单的,但我无法找到解决方案。

请帮忙!

问候,
卡维亚

专家解答

这里的挑战是,你需要做一个 * 动态 * 枢轴,即,列数是未知的,直到你看数据。Stew Ashton在这里写了一篇关于如何做到这一点的好博客文章

https://stewashton.wordpress.com/2018/05/28/generic-pivot-function/

我会用它来帮助解决这个问题。我也使用了日期数据类型,因为从来没有使用数字数据。

首先,我可以生成我需要的月份

SQL> Create table program_det (program_name varchar2(50), program_date date);

Table created.

SQL> Insert into program_det values('PROGRAM_1', date '2018-01-01');

1 row created.

SQL> Insert into program_det values('PROGRAM_1', date '2018-07-01');

1 row created.

SQL> COMMIT;

Commit complete.

SQL>
SQL>
SQL> with pgm as
  2  ( select program_name,
  3                 min(program_date) mind,
  4                 max(program_date) maxd
  5          from program_det
  6          group by program_name )
  7  select *
  8  from  pgm p,
  9        table(cast(multiset(
 10            select add_months(p.mind,rownum-1)
 11            from   pgm
 12            where  program_name = p.program_name
 13            connect by add_months(mind,rownum-1) <= p.maxd
 14            ) as sys.odcidatelist));

PROGRAM_NAME                                       MIND      MAXD      COLUMN_VA
-------------------------------------------------- --------- --------- ---------
PROGRAM_1                                          01-JAN-18 01-JUL-18 01-JAN-18
PROGRAM_1                                          01-JAN-18 01-JUL-18 01-FEB-18
PROGRAM_1                                          01-JAN-18 01-JUL-18 01-MAR-18
PROGRAM_1                                          01-JAN-18 01-JUL-18 01-APR-18
PROGRAM_1                                          01-JAN-18 01-JUL-18 01-MAY-18
PROGRAM_1                                          01-JAN-18 01-JUL-18 01-JUN-18
PROGRAM_1                                          01-JAN-18 01-JUL-18 01-JUL-18

7 rows selected.


现在,为了便于阅读,我将创建一个视图

SQL> create or replace view v as
  2  with pgm as
  3  ( select program_name,
  4                 min(program_date) mind,
  5                 max(program_date) maxd
  6          from program_det
  7          group by program_name )
  8  select program_name,
  9         to_char(column_value,'YYYYMM') mth
 10  from  pgm p,
 11        table(cast(multiset(
 12            select add_months(p.mind,rownum-1)
 13            from   pgm
 14            where  program_name = p.program_name
 15            connect by add_months(mind,rownum-1) <= p.maxd
 16            ) as sys.odcidatelist));

View created.


然后我将它传递到通用枢轴中

SQL> set serveroutput off
SQL> var rc refcursor
SQL> begin
  2        :rc := generic_pivot(
  3          '(select program_name, mth, 0 val from v)',
  4          'MTH',
  5          'SUM(VAL)'
  6        );
  7      end;
  8  /

PL/SQL procedure successfully completed.

SQL> print rc

PROGRAM_NAME                                           201801     201802     201803     201804     201805     201806     201807
-------------------------------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
PROGRAM_1


我在那里硬编码了零,但是你会加入或类似的方式来获得你想要呈现的数字数据。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论