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));

  

 

 至此,問題得到解決,如大神還有其他處理方法,歡迎在評論區留言,小弟願聞其詳。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM