欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Oracle中行列轉(zhuǎn)換有哪些方法

 更新時(shí)間:2023年08月02日 10:36:13   作者:客逍京北岸  
這篇文章主要給大家介紹了關(guān)于Oracle中行列轉(zhuǎn)換有哪些方法的相關(guān)資料,最近在工作中遇到了涉及到數(shù)據(jù)庫行列之間相互轉(zhuǎn)換的問題,所以這里給大家總結(jié)介紹下,需要的朋友可以參考下

前言

行列轉(zhuǎn)換是指將行數(shù)據(jù)轉(zhuǎn)換為列數(shù)據(jù),或?qū)⒘袛?shù)據(jù)轉(zhuǎn)換為行數(shù)據(jù)的過程。這通常使用的辦法是用PIVOT和UNPIVOT函數(shù)來實(shí)現(xiàn)。這里描述兩種方法分別實(shí)現(xiàn)行列轉(zhuǎn)換?。?!

首先創(chuàng)建表:

  • 學(xué)生表:student;--包括學(xué)生號(hào),姓名,年紀(jì),性別,生日
  • 教師表:teacher;--包括教師編號(hào),姓名
  • 課程表:course;--包括課程編號(hào),課程名稱,對(duì)應(yīng)教師
  • 學(xué)生成績表:sc;--包括學(xué)生號(hào),課程編號(hào),成績

創(chuàng)建表的腳本如下:

--學(xué)生 student表
drop table student;
create table student(
sno varchar2(10) primary key,
sname varchar2(20),
sage number(2),
ssex varchar2(5),
birthday date
);
--教師 teacher表
drop table teacher;
create table teacher(
tno varchar2(10) primary key,
tname varchar2(20)
);
--課程 course表
drop table course;
create table course(
cno varchar2(10),
cname varchar2(20),
tno varchar2(20),
constraint pk_course primary key (cno,tno)
);
--學(xué)生成績 sc表
drop table sc;
create table sc(
sno varchar2(10),
cno varchar2(10),
score number(4,2),
constraint pk_sc primary key (sno,cno)
);
/*******初始化學(xué)生表的數(shù)據(jù)******/
insert into student values ('s001','張亍卬',FLOOR(months_between(SYSDATE,date '2000-3-5')/12),'男',date '2000-3-5');
insert into student values ('s002','李殳戔',FLOOR(months_between(SYSDATE,date '2001-2-3')/12),'男',date '2001-2-3');
insert into student values ('s003','吳仝玓',FLOOR(months_between(SYSDATE,date '2002-5-8')/12),'男',date '2002-5-8');
insert into student values ('s004','琴甪',FLOOR(months_between(SYSDATE,date '2000-6-15')/12),'女',date '2000-6-15');
insert into student values ('s005','王讱纊',FLOOR(months_between(SYSDATE,date '2000-8-12')/12),'女',date '2000-8-12');
insert into student values ('s006','李孖伣',FLOOR(months_between(SYSDATE,date '2001-9-20')/12),'男',date '2001-9-20');
insert into student values ('s007','劉辿吒',FLOOR(months_between(SYSDATE,date '2002-10-5')/12),'男',date '2002-10-5');
insert into student values ('s008','蕭竦俐',FLOOR(months_between(SYSDATE,date '2003-6-1')/12),'女',date '2003-6-1');
insert into student values ('s009','陳閆邠邡',FLOOR(months_between(SYSDATE,date '2001-1-15')/12),'女',date '2001-1-15');
insert into student values ('s010','陳芃伋',FLOOR(months_between(SYSDATE,date '2001-1-9')/12),'女',date '2001-1-9');
commit;
/******************初始化教師表***********************/
insert into teacher values ('t001', '龔陽');
insert into teacher values ('t002', '諶燕');
insert into teacher values ('t003', '武明星');
commit;
/***************初始化課程表****************************/
insert into course values ('c001','J2SE','t002');
insert into course values ('c002','Java Web','t001');
insert into course values ('c003','SSH','t001');
insert into course values ('c004','Oracle','t001');
insert into course values ('c005','SQL SERVER 2005','t003');
insert into course values ('c006','C#','t003');
insert into course values ('c007','JavaScript','t003');
insert into course values ('c008','DIV+CSS','t001');
insert into course values ('c009','PHP','t003');
insert into course values ('c010','EJB3.0','t002');
commit;
/***************初始化成績表***********************/
insert into sc values ('s001','c001',78);
insert into sc values ('s002','c001',80);
insert into sc values ('s003','c001',81);
insert into sc values ('s004','c001',60);
insert into sc values ('s001','c002',82);
insert into sc values ('s002','c002',72);
insert into sc values ('s003','c002',81);
insert into sc values ('s001','c007',88);
insert into sc values ('s001','c010',73);
insert into sc values ('s002','c003',69);
insert into sc values ('s002','c008',92);
insert into sc values ('s002','c009',81);
insert into sc values ('s002','c007',85);
insert into sc values ('s002','c010',75);
insert into sc values ('s005','c001',63);
insert into sc values ('s005','c002',96);
insert into sc values ('s005','c007',75);
insert into sc values ('s005','c010',72);
insert into sc values ('s006','c001',72);
insert into sc values ('s007','c001',61);
insert into sc values ('s008','c001',92);
insert into sc values ('s009','c001',58);
insert into sc values ('s010','c001',85);
insert into sc values ('s002','c004',80);
insert into sc values ('s002','c005',70);
insert into sc values ('s002','c006',60);
commit;

一、行轉(zhuǎn)列(一)

使用case when/decode+聚合函數(shù)+group by的方法實(shí)現(xiàn)行轉(zhuǎn)列;

把sc表進(jìn)行行轉(zhuǎn)列查詢出每個(gè)學(xué)生每門課程的成績:

原sc表:

SELECT * FROM sc;--學(xué)生成績表

執(zhí)行結(jié)果展示其中一部分:

 此時(shí)要對(duì)cno課程編號(hào)進(jìn)行行轉(zhuǎn)列:

select sno,sum(case cno when 'c001' then score end) c001,
           sum(case cno when 'c002' then score end) c002,
           sum(case cno when 'c003' then score end) c003,
           sum(case cno when 'c004' then score end) c004,
           sum(case cno when 'c005' then score end) c005,
           sum(case cno when 'c006' then score end) c006,
           sum(case cno when 'c007' then score end) c007,
           sum(case cno when 'c008' then score end) c008,
           sum(case cno when 'c009' then score end) c009,
           sum(case cno when 'c0010' then score end) c0010
from sc
group by sno  
order by sno;

執(zhí)行結(jié)果:

展示的為每個(gè)學(xué)生他的每一門課程成績;

總結(jié):

要求把查詢的哪一列轉(zhuǎn)成列名就放在case后面,并把它的列中值進(jìn)行分類放在when后面;

比如學(xué)生成績表總共就三列(學(xué)生號(hào),課程編號(hào),學(xué)生成績),我們要查詢每個(gè)學(xué)生的每科成績展示,就需要對(duì)課程編號(hào)cno進(jìn)行分類轉(zhuǎn)換,因此把課程編號(hào)cno放在case后面,然后把課程編號(hào)cno中所包含的所有值進(jìn)行分類,即全部課程科目c001--c0010,分類放在when的后面!!

要把哪一列內(nèi)容放在列中值中就放在then 后面;

意思就是我們最后要看的結(jié)果值,比如對(duì)應(yīng)上面查詢,要查看的是學(xué)生成績score,此時(shí)就把學(xué)生成績score放在then的后面即可。

這種辦法可以實(shí)現(xiàn)我們對(duì)需求的解決實(shí)現(xiàn),但是使用比較麻煩,可能會(huì)理解錯(cuò)誤,而且代碼語句寫的比較多,因此可以換種方法來更簡單實(shí)現(xiàn)行轉(zhuǎn)列!??!

二、行轉(zhuǎn)列(二) 

使用PIVOT函數(shù),可以將行數(shù)據(jù)轉(zhuǎn)換為列數(shù)據(jù),并且可以在同一查詢中匯總和篩選數(shù)據(jù)。

基本語法格式如下:

PIVOT(被聚合的列 FOR 行轉(zhuǎn)列的列 in(列中值1,列中值2...))
select *
from  表
pivot (聚合函數(shù)(被聚合的列) for 行轉(zhuǎn)列的列 in (列中值1,,列中值2植..))

批注:

  • 被聚合的列:變成列中值的列;
  • 行轉(zhuǎn)列的列:由列中值變?yōu)榱忻牧?; 
  • 列中值1,列中值2..:新增加的列名(即為行轉(zhuǎn)列的列中的列中值)就是列中值1,列中值2...。
  • 備注:被聚合的列要加聚合函數(shù)。

或者另一種理解:

SELECT *
FROM (SELECT column1, column2, column3 FROM table_name)
PIVOT (aggregate_function(column2) 
       FOR column1 IN ('value1' AS alias1, 'value2' AS alias2, ...));

其中,PIVOT中的column1是要轉(zhuǎn)換為列的列,column2是要匯總的列,alias是列的別名。

那么此時(shí)“把sc表行轉(zhuǎn)列查詢每個(gè)學(xué)生每門課程的成績”可寫為:

select *
from sc
pivot(sum(score) for cno in('c001' c001,'c002' c002,'c003' c003,'c004' c004,
                'c005' c005,'c006' c006,'c007' c007,'c008' c008,'c009' c009,'c010' c010))
order by sno;

其中,as可加可不加,對(duì)于列中值一定要加單引號(hào)。同時(shí)運(yùn)行結(jié)果是和之前的一致。如圖所示:

使用PIVOT函數(shù)時(shí),需要注意以下幾點(diǎn):

  • PIVOT函數(shù)必須在FROM子句中使用,因此需要將原始查詢包裝在一個(gè)子查詢中。
  • aggregate_function是要應(yīng)用于column2的聚合函數(shù),可以是SUM、AVG、COUNT、MAX、MIN等。
  • FOR子句指定要在新列中顯示的值。在IN子句中指定這些值,并在別名中指定新列的名稱。

三、列轉(zhuǎn)行(一)

使用union all方法實(shí)現(xiàn)列轉(zhuǎn)行;

比如:有一張員工表emp,請(qǐng)用一條sql顯示如下格式 

  ENPNO  KEY     VALUE 
  7369  ENAME    SMITH
  7369  JOB      CLERK
  7369  MGR      7902

先看原員工表格式:

select * from emp;

通過對(duì)比發(fā)現(xiàn)是將原表中的列和其對(duì)應(yīng)值轉(zhuǎn)換為行式展現(xiàn),同時(shí)為其定義了新的列名分別為ENPNO 、KEY 、VALUE 。那么用union all的方式實(shí)現(xiàn)的語句為:

select * from 
  (select empno,'ENAME' KEY,ENAME VALUE FROM EMP 
  UNION ALL
  select empno,'JOB' KEY,TO_CHAR(JOB) VALUE FROM EMP
  UNION ALL
  select empno,'MGR' KEY,TO_CHAR(MGR) VALUE FROM EMP
  UNION ALL
  select empno,'HIREDATE' KEY,TO_CHAR(HIREDATE) VALUE FROM EMP
  UNION ALL
  select empno,'SAL' KEY,TO_CHAR(SAL) VALUE FROM EMP
  UNION ALL
  select empno,'COMM' KEY,TO_CHAR(COMM) VALUE FROM EMP
  UNION ALL
  select empno,'DEPTNO' KEY,TO_CHAR(DEPTNO) VALUE FROM EMP)
WHERE EMPNO=7369;

簡單理解為:查詢?cè)搯T工編號(hào)對(duì)應(yīng)的每一條列信息,對(duì)列中值進(jìn)行格式轉(zhuǎn)換統(tǒng)一,然后使用union all進(jìn)行并集為一個(gè)數(shù)據(jù)集合作為參考表,最后加判斷條件完成列轉(zhuǎn)換。那么看下這種方式的運(yùn)行結(jié)果:

通過改圖發(fā)現(xiàn)確實(shí)已經(jīng)完成了目的需求的格式轉(zhuǎn)換。不過此方法同樣比較繁瑣,代碼量也比較多,所以可以換另外一種方法實(shí)現(xiàn)同樣的效果。

四、列轉(zhuǎn)行(二)

UNPIVOT函數(shù)可以將列數(shù)據(jù)轉(zhuǎn)換為行數(shù)據(jù)。基本語法如下:

unpivot 列轉(zhuǎn)行自動(dòng)去空 如果要留住空值 在unpivot 后加上 include nulls
 
unpivot(被聚合的列的新列名 for  列轉(zhuǎn)行的列的新列名 in (字段1,字段2...))

被聚合的列的新列名:指的是目標(biāo)結(jié)果集的列名,按照目標(biāo)結(jié)果集來填寫,即原來聚合的數(shù)據(jù)如這里的nums,列轉(zhuǎn)行之前的列中值放在取了新名字的這個(gè)列中;

列轉(zhuǎn)行的列的新列名:指的是要列轉(zhuǎn)行的列名的集合新名字,既創(chuàng)建一個(gè)新的列來存儲(chǔ)要列轉(zhuǎn)行的列,如這里的name,他的列中值在列傳行之前為原視圖的多個(gè)列;

字段1,字段2...:指的是要列轉(zhuǎn)行的列名,既為要放到列轉(zhuǎn)行的列的新列名里的列中值,就是列轉(zhuǎn)行之前視圖的多個(gè)列。

完整格式:

SELECT *
FROM table_name
UNPIVOT (column3 FOR column1 IN (column2, column3, ...));

column1是要轉(zhuǎn)換為行的列,column2和column3是要轉(zhuǎn)換的列。

那么此時(shí)使用UNPIVOT函數(shù)完成上個(gè)問題的列轉(zhuǎn)行方法就可以寫為:

select *
from (SELECT empno,ENAME,JOB,
             TO_CHAR(MGR) MGR,
             TO_CHAR(HIREDATE) HIREDATE,
             TO_CHAR(SAL) SAL,
             TO_CHAR(COMM) COMM,
             TO_CHAR(DEPTNO) DEPTNO
      FROM EMP
      WHERE EMPNO=7369)
unpivot include nulls(VALUE for KEY IN(ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO));

這里在列轉(zhuǎn)行時(shí)對(duì)表中每一列做了格式統(tǒng)一,最后運(yùn)行結(jié)果和第一種方法一樣。如圖所示:

使用UNPIVOT函數(shù)時(shí),需要注意以下幾點(diǎn):

  • UNPIVOT函數(shù)必須在FROM子句中使用,因此需要將原始查詢包裝在一個(gè)子查詢中。
  • FOR子句指定要轉(zhuǎn)換為行的列。
  • IN子句指定要轉(zhuǎn)換的列。

總結(jié)

到此這篇關(guān)于Oracle中行列轉(zhuǎn)換有哪些方法的文章就介紹到這了,更多相關(guān)Oracle行列轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論