回覆列表
-
1 # 五星村小黃
-
2 # 小R老師說oracle
SELECT行列轉換
前幾天有一個群友在群裡面(190359237)有問到列轉換成行的問題,今天終於有時間坐下來查閱資料做一個方法彙總,自己學習一下,也僅以此方式將這些分享給大家。第一部分:行轉列新建一個表:CREATE TABLE HANG2LIE( "ID" NUMBER,"NAME" VARCHAR2(20),"COURSE" VARCHAR2(20),"SCORE" NUMBER)在表中插入如下的資料(為了鍛鍊下pl/sql所以這裡費事寫了一個PL/SQL程式):declare random_var number; course_var varchar2(20);beginfor i in 1..3 loop for j in 1..5 loop select mod(trunc(dbms_random.value(0,100)*190),100) into random_var from dual; case when j=1 then course_var:="語文"; when j=2 then course_var:="數學"; when j=3 then course_var:="英語"; when j=4 then course_var:="歷史"; when j=5 then course_var:="化學"; end case; insert into HANG2LIE(id,name,course,score) values(i,"name_" || i,course_var,random_var); end loop;end loop;end;/資料列出來如下: ID NAME COUR SCORE--- ------- ---- ----- 1 name_1 語文 33 1 name_1 數學 63 1 name_1 英語 71 1 name_1 歷史 68 1 name_1 化學 94 2 name_2 語文 85 2 name_2 數學 4 2 name_2 英語 98 2 name_2 歷史 9 2 name_2 化學 12 3 name_3 語文 49 3 name_3 數學 96 3 name_3 英語 30 3 name_3 歷史 60 3 name_3 化學 2要實現的行轉列的效果如下(或者類似的結果): ID NAME SCORES--- ------- -------------------- 1 name_1 33,63,71,94,68 2 name_2 85,4,98,12,9 3 name_3 49,2,60,96,301、透過Oracle資料庫自帶的wm_concat()函式來實現:select id,name,wm_concat(score) scoresfrom HANG2LIEgroup by id,name;2、透過decode函式:select id,name,sum(decode(course,"語文",score,null)) "語文",sum(decode(course,"數學",score,null)) "數學",sum(decode(course,"英語",score,null)) "英語",sum(decode(course,"歷史",score,null)) "歷史",sum(decode(course,"化學",score,null)) "化學"from HANG2LIEgroup by id,name;得到的結果: ID NAME 語文 數學 英語 歷史 化學--- ------- ---------- ---------- ---------- ---------- ---------- 2 name_2 85 4 98 9 12 1 name_1 33 63 71 68 94 3 name_3 49 96 30 60 23、透過case表示式select id,name,sum(case when course="語文" then score end) "語文",sum(case when course="數學" then score end) "數學",sum(case when course="英語" then score end) "英語",sum(case when course="歷史" then score end) "歷史",sum(case when course="化學" then score end) "化學"from HANG2LIEgroup by id,name;得到的結果和第二種實際上是一樣的,其實語句也是一樣的,只不過把decode函式換成了case when表示式而已第二部分:列轉行
圖省力呢,根據上面的表新建一個表:create table lie2hang asselect id,name,sum(case when course="語文" then score end) Chinese,sum(case when course="數學" then score end) Math,sum(case when course="英語" then score end) English,sum(case when course="歷史" then score end) History,sum(case when course="化學" then score end) Chemistryfrom hang2liegroup by id,name;結構如下: ID NAME Chinese Math English History Chemistry--- ------- ---------- ---------- ---------- ---------- ---------- 2 name_2 85 4 98 9 12 1 name_1 33 63 71 68 94 3 name_3 49 96 30 60 2我們要實現如下的查詢效果: ID NAME COUR SCORE--- -------- ---- ----- 2 name_2 語文 85 1 name_1 語文 33 3 name_3 語文 49 2 name_2 數學 4 1 name_1 數學 63 3 name_3 數學 96 2 name_2 英語 98 1 name_1 英語 71 3 name_3 英語 30 2 name_2 歷史 9 1 name_1 歷史 68 3 name_3 歷史 60 2 name_2 化學 12 1 name_1 化學 94 3 name_3 化學 21、集合查詢實現的SQL語句:select id,name,"語文" course,chinese score from lie2hangunionselect id,name,"數學" course,math score from lie2hangunionselect id,name,"英語" course,english score from lie2hangunionselect id,name,"歷史" course,history score from lie2hangunionselect id,name,"化學" course,chemistry score from lie2hang;這就是比較常見的列傳行操作,主要原理是利用SQL的union集合查詢。2、insert all操作語句如下:create table lie2hang_result(id number,name varchar2(20),course varchar2(20),score number);insert allinto lie2hang_result(id,name,course,score) values(id,name,"語文",chinese)into lie2hang_result(id,name,course,score) values(id,name,"數學",math)into lie2hang_result(id,name,course,score) values(id,name,"英語",english)into lie2hang_result(id,name,course,score) values(id,name,"歷史",history)into lie2hang_result(id,name,course,score) values(id,name,"化學",chemistry)select id,name,chinese,math,english,history,chemistry from lie2hang;這樣的結果和第一種方法的相同,不過貌似不大好像起來用這個哈! -
3 # 小逗電競
這個問題我可以回答您。
在oracle中有兩個牛逼的函式,分別是:wmsys.wm_concat和
scott.listagg
, 可以實現行列轉換,非常簡單,也是我們日常開發及運維工作中經常用得到的兩個函式。wm_concat是oracle 10g推出的一個行列轉換函式,而
scott.listagg
是oracle 11g中推出的,兩者作用一樣,但使用上稍有差異。例子:
我們建立一個員工資訊表:EMP,表中有三個欄位,分別是:
EMPNO:員工編號
NAME:員工姓名
DEPTNO:部門編號
建表SQL:
create table EMP (empNo varchar(50),name varchar(30),deptNo varchar2(50));手動插入部分資料:
insert into EMP values("11","ZK01","1");insert into EMP values("12","ZK02","2");insert into EMP values("13","ZK03","3");insert into EMP values("14","ZK04","4");insert into EMP values("15","ZK05","1");insert into EMP values("16","ZK06","2");insert into EMP values("17","ZK07","3");insert into EMP values("18","ZK08","4");insert into EMP values("19","ZK09","1");insert into EMP values("20","ZK10","2");insert into EMP values("21","ZK11","3");insert into EMP values("22","ZK12","4");insert into EMP values("23","ZK13","5");現在我們的需求是要透過SQL查出每一個部門下都有哪些員工,員工要求在一行展示,員工之間用逗號隔開。
1、函式 wmsys.wm_concat
用法:wmsys.wm_concat(列名),該函式可以把列值用逗號隔開,在一行顯示。
select T1.deptno,to_char(wmsys.wm_concat(T1.name)) from emp T1 group by T1.deptno order by T1.deptno asc結果:已經達我們的預期。
2、函式
scott.listagg
用法:listagg(列名,分隔符) + within group(order by 列名)
select T1.deptno,listagg(T1.name, ",") within group(order by T1.deptno) name from emp T1 group by T1.deptno order by T1.deptno asc結果:也達到我們的預期。
這個有很多種方式,我給你寫一個常見的, 使用decode, 比如你要行轉列
student subject grade
-------------------------
張三 語文 80
張三 數學 70
張三 英語 60
李四 語文 90
李四 數學 80
李四 英語 100
-------------------------
轉換為:
-------------------------
學生 語文 數學 英語
張三 80 70 60
李四 90 80 100
-------------------------
select student "學生",
sum(decode(subject,"語文", grade,null)) "語文",
sum(decode(subject,"數學", grade,null)) "數學",
sum(decode(subject,"英語", grade,null)) "英語"
from table
group by student;