首先我們來看下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));
至此,問題得到解決,如大神還有其他處理方法,歡迎在評論區留言,小弟願聞其詳。