oracle行列转换
2020-11-05 本文已影响0人
爱恨_交加
行转列
建表、插数
create table transcript
(
id NUMBER,
name VARCHAR2(20),
course VARCHAR2(20),
score NUMBER
);
insert into transcript (id, name, course, score) values (1, '张三', '语文', 67);
insert into transcript (id, name, course, score) values (1, '张三', '数学', 76);
insert into transcript (id, name, course, score) values (1, '张三', '英语', 43);
insert into transcript (id, name, course, score) values (2, '李四', '语文', 54);
insert into transcript (id, name, course, score) values (2, '李四', '数学', 81);
insert into transcript (id, name, course, score) values (2, '李四', '英语', 64);
insert into transcript (id, name, course, score) values (3, '王五', '语文', 24);
insert into transcript (id, name, course, score) values (3, '王五', '数学', 25);
insert into transcript (id, name, course, score) values (3, '王五', '英语', 8);
commit;
转换方式
CASE
-- 可以使用 MAX替代 SUM,但 MIN 不可以
SELECT ID,NAME,
SUM(CASE WHEN course='语文' THEN score ELSE 0 END) 语文,
SUM(CASE WHEN course='数学' THEN score ELSE 0 END) 数学,
SUM(CASE WHEN course='英语' THEN score ELSE 0 END) 英语
FROM transcript
GROUP BY ID ,NAME
DECODE
-- 可以使用 SUM 替代 MAX,但 MIN 不可以
SELECT ID,NAME,
MAX(DECODE(course,'语文',score,0)) 语文,
MAX(DECODE(course,'数学',score,0)) 数学,
MAX(DECODE(course,'英语',score,0)) 英语
FROM transcript
GROUP BY ID ,NAME
PIVOT
SELECT * FROM transcript
PIVOT(SUM(score) FOR course IN('语文' as 语文,'数学' as 数学,'英语' as 英语));
wmsys.wm_concat
SELECT ID,NAME,
wmsys.wm_concat(course || ':'||score) course
FROM transcript
GROUP BY ID,NAME;
PL/SQL
DECLARE
--判断表是否存在
TAB_EXISTS INTEGER;
--存放最终的SQL
LV_SQL VARCHAR2(3000);
--存放连接的SQL
SQL_COMMOND VARCHAR2(3000);
--定义课程游标
CURSOR CUR IS
SELECT COURSE FROM transcript GROUP BY COURSE;
BEGIN
--定义查询开头
SQL_COMMOND := 'SELECT ID,NAME ';
FOR I IN CUR LOOP
--将结果相连接
SQL_COMMOND := SQL_COMMOND || ' ,SUM(DECODE(COURSE,''' || I.COURSE || ''',SCORE,0)) ' || I.COURSE;
DBMS_OUTPUT.PUT_LINE(SQL_COMMOND);
END LOOP;
SQL_COMMOND := SQL_COMMOND || ' FROM TRANSSCRIPT GROUP BY NAME';
-- 判断表是否存在,存在则删除
SELECT COUNT(*) INTO TAB_EXISTS FROM USER_TABLES WHERE table_name = 'TRANSSCRIPT_TMP';
IF TAB_EXISTS > 0 THEN
DBMS_OUTPUT.PUT_LINE('该表已经存在!');
EXECUTE IMMEDIATE 'DROP TABLE TRANSSCRIPT_TMP';
ELSE
DBMS_OUTPUT.PUT_LINE('该表并不存在!');
END IF;
--生成并执行最终SQL
LV_SQL := 'CREATE TABLE TRANSSCRIPT_TMP ' || SQL_COMMOND;
DBMS_OUTPUT.PUT_LINE(LV_SQL);
EXECUTE IMMEDIATE LV_SQL;
END;
--查询结果
SELECT * FROM TRANSCRIPT_TMP;
列转行
建表、插数
create table transcript
(
id NUMBER,
name VARCHAR2(20),
语文 NUMBER,
数学 NUMBER,
英语 NUMBER
);
insert into transcript (id,name,语文,数学,英语) values(1,'张三',71,72,73);
insert into transcript (id,name,语文,数学,英语) values(2,'李四',81,82,83);
insert into transcript (id,name,语文,数学,英语) values(3,'王五',91,92,93);
commit;
转换方式
UNPIVOT
select id,name, course, score
from transcript
unpivot((score) for course in(语文,数学,英语));