oracle行转列之动态列

首先我们来看下oracle的行转列函数:

pivot 函数官方解释:https://www.oracle.com/cn/database/articles/technology/pivot-and-unpivot.html

首先我们创建相关表及数据

create table TEST_DATA
(
  goods_name   VARCHAR2(32),
  budget_date  VARCHAR2(32),
  budget_money NUMBER
);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('泡面', '2020-01', 20);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('泡面', '2020-02', 50);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('泡面', '2020-03', 60);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('火腿', '2020-01', 210);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('火腿', '2020-02', 530);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('火腿', '2020-03', 640);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('牛奶', '2020-01', 120);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('牛奶', '2020-02', 160);
insert into test_data (GOODS_NAME, BUDGET_DATE, BUDGET_MONEY)values ('牛奶', '2020-03', 140);

 我们的数据是这样的:

 

 

 

 我们需要的结果是:

名称  2020-01  2020-02  2020-03  .。。。

泡面  20      50    60

火腿  210     530    640

牛奶  120     650    140

假如我们知道我们要转换的列为 2020-01 至2020-03 这时可以做如下转换:

select * from test_data 
pivot (sum(budget_money) for budget_date in('2020-01','2020-02','2020-03'));

  

 

 

 但是当月份不确定时,上面这种写法就不适用了。我们查看官方文档后发现  pivot 操作中的另一个子句 XML 可用于解决此问题。该子句允许您以 XML 格式创建执行了 pivot 操作的输出。这个时候我们将上面查询语句改造之后如下:

select * from test_data 
pivot xml (sum(budget_money) for budget_date in(select budget_date from  test_data));

  

 

 该语句在不同版本的plsql中类型不同,在plsql14001961版本中显示xmltype类型。

这时查看budget_date_xml的值发现会将表中所有月份展示,结果如下

 

 当我高兴的认为我的问题解决了之后,我发现我草率了。

将sql放到mybatis中查询出来的结果没法办解析,网上找了一圈之后说是让你加一个xdb6.jar和xmlparserv2.jar,加完还是报错,最终找到可以在数据库层面将xmltype转换长varchar2

select goods_name,(BUDGET_DATE_xml).getstringval() from test_data 
pivot xml (sum(budget_money) for budget_date in(select budget_date from  test_data));

  

 

 此时觉得已经ok了,但是屁股还没坐热就出现了新问题,varchar2最长4000,月份过多时会出现缓冲池内存不足的问题。这时心想可不可以转成colb这样就不会有问题了,抱着侥幸心理试了下getclobval,没想到还真有这方法!

select goods_name,(BUDGET_DATE_xml).getclobval() from test_data 
pivot xml (sum(budget_money) for budget_date in(select budget_date from  test_data));

  

 

 至此,问题得到解决,如大神还有其他处理方法,欢迎在评论区留言,小弟愿闻其详。

posted @ 2020-09-03 16:17  氢夏  阅读(3919)  评论(0编辑  收藏  举报