7.oracle集合运算与行列转换

--并集,交集,差集
1.并集去重 union 去重以第一个字段排序显示
2.并集不去重 union all 将两个字段合并 不排序;
--列名以第一个表字段显示,两个表对应字段数据类型相同,字段可以不同
SELECT DEPTNO AS 编号,dname as 名称 from dept
union
select empno,ename from emp;

select deptno from dept
union 
select deptno from dept;

select deptno from dept
union all
select deptno from dept;

3. intersect-交集 将两个查询结果共有的数据去重,排序;
select job ROM EMP WHERE DEPTNO=10
INTERSECT
SELECT JOB FROM EMP WHERE DEPTNO=20;

4.差集-minus 取仅在第一个表中存在的数据,去重,排序;
select DEPTNO FROM DEPT
MINUS
SELECT DEPTNO FROM EMP;
SELECT DEPTNO FROM EMP
MINUS
select DEPTNO FROM DEPT;
注意点:除了 union all 其他的都去重,别名写在第一个查询,排序写在最后一个查询,排序写在第一个报错;
        综合集合运算从上到下一次执行;



----行列转换
建立行列转换随需表
--第一个表--------
三个字段;--姓名-科目-成绩
CREATE TABLE SCORE_1(STUDENT VARCHAR2(12),COURSE VARCHAR2(7),SCORE NUMBER);
SELECT * FROM SCORE_1;
INSERT INTO SCORE_1 VALUES('张三','CHINESE',70);
INSERT INTO SCORE_1 VALUES('张三','ENGLISH',90);
INSERT INTO SCORE_1 VALUES('张三','MATH',80);
INSERT INTO SCORE_1 VALUES('李四','CHINESE',76);
INSERT INTO SCORE_1 VALUES('李四','ENGLISH',91);
INSERT INTO SCORE_1 VALUES('李四','MATH',82);
INSERT INTO SCORE_1 VALUES('王五','CHINESE',85);
INSERT INTO SCORE_1 VALUES('王五','ENGLISH',70);
INSERT INTO SCORE_1 VALUES('王五','MATH',90);
COMMIT;
--建立第二个表 四个字段--姓名-CHINESE成绩--MATH成绩--ENGLISH成绩
CREATE TABLE SCORE_2(STUDENT VARCHAR2(12),CHINESE NUMBER,MATH NUMBER,ENGLISH NUMBER);
INSERT INTO SCORE_2 VALUES('张三',70,80,90);
INSERT INTO SCORE_2 VALUES('李四',76,82,91);
INSERT INTO SCORE_2 VALUES('王五',85,90,70);
COMMIT;
SELECT * FROM SCORE_2;  --插入数据之后查看一下表
SELECT * FROM SCORE_1;
---行列转换实现方法
1.传统方法
将某一维度的内容拆解成多个新的列:聚合函数+CASE WHEN语句
通过聚合函数,case when 分组函数实现 语法如下:
sum() case when... group by 再搭配集合运算实现

select t.*,case when COURSE='CHINESE' then score else 0 end CHINESE,        
           case when COURSE='ENGLISH' then score else 0 end CHINESE,
           case when COURSE='MATH' then score else 0 end CHINESE
 from SCORE_1 t;

/*select student,sum(score) score,sum(chinese) chinese,sum( math) math from (
select t.*,case when COURSE='CHINESE' then score else 0 end CHINESE,        
           case when COURSE='ENGLISH' then score else 0 end english,
           case when COURSE='MATH' then score else 0 end math
 from SCORE_1 t
) group by student;*/

SELECT STUDENT,SUM(CASE WHEN COURSE='CHINESE' THEN SCORE ELSE 0 END) CHINESE,
               SUM(CASE WHEN COURSE='MATH' THEN SCORE ELSE 0 END) MATH,
               SUM(CASE WHEN COURSE='ENGLISH' THEN SCORE ELSE 0 END) ENGLISH
               FROM SCORE_1 GROUP BY STUDENT;
               
聚合函数+decode函数
DECODE语法;
DECODE(EXPR,VALUE1,RESULT1,VALUE2,RESULT2,…,DEF_RESULT);
select student,sum(decode(course,'CHINESE',SCORE,0)) CHINESE,
               sum(decode(course,'MATH',SCORE,0)) MATH,
               sum(decode(course,'ENGLISH',SCORE,0)) ENGLiSH
               FROM SCORE_1 GROUP BY STUDENT;
               
列转行(将SCORE_2转换成SCORE_1);
将多个列合并成为一个新的维度:单查多列+并集运算(UNION ALL);
select student,'chinese' as course,chinese score from score_2
union all 
select student,'math' as course,math score from score_2
union all
select student,'english' as course,english score from score_2;
/*之所以使用UNION ALL而不用UNION的原因是因为UNION ALL不会将重复的数据去掉,确保了数据的完整性,
而UNION会先去重再合并,可能会导致合并的数据不完整。*/

2.专用函数(pivot/unpivot)(都写在FROM后面)
2.1行转列 (将SCORE_1转为SCORE_2)--PIVOT 将维度数据拆解成多个列 --对应  SUM(CASE WHEN ...)和 SUM(DECODE())
语法:


SELECT * FROM TB PIVOT(SUM(TB.COL1) FOR TB.COL2 IN (VAL1 AS NEW_COL1,VAL2 AS NEW_COL2,VAL3 AS NEW_COL3));
PIVOT函数注释:
PIVOT函数内一定要有聚合函数 MAX()
TB.COL1:被聚合分析的字段  SCORE
TB.COL2:被拆解的字段  COURSE
VAL1,VAL2,VAL3...:TB.COL2字段中的某值
NEW_COL1,NEW_COL2,NEW_COL3...:TB.COL2字段拆解后形成的新字段
AS NEW_COL部分可以不写,最终会以VAL作为字段名展示
SELECT *
  FROM 表名
PIVOT(MAX(列名)   [要转成的字段下的数据]
FOR 要转的列 IN('要转的列下的字符名' AS 转成的列名,
               '要转的列下的字符名' AS 转成的列名,
               '要转的列下的字符名' AS 转成的列名,
               '要转的列下的字符名' AS 转成的列名))
WHERE 1 = 1; --没有条件可以不写
select * from score_1 pivot(max(score) for course in ('CHINESE' as chinese,
                                                  'ENGLISH' as english,
                                                  'MATH' as math));                                            
select * from score_1 pivot(max(score) for STUDENT in ('王五' as wangwu,
                                                  '李四' as lisi,
                                                  '张三' as zhangsan));                                                 
2.2列转行(将SCORE_2转为SCORE_1)--UNPIVOT 将多个列合并成一个新的维度 --对应 UNION ALL
--语法:
SELECT * FROM TB UNPIVOT(NEW_COL1 FOR NEW_COL2 IN (TB.COL1 AS VAL1,TB.COL2 AS VAL2,TB.COL3 AS VAL3));
/*UNPIVOT函数注释:
UNPIVOT函数内不需要聚合函数
NEW_COL1:用来收纳交叉数据的字段,字段名自取 SCORE
NEW_COL2:新合成的维度字段,字段名自取   COURSE

TB.COL1,TB.COL2,TB.COL3...:被并入的字段
VAL1,VAL2,VAL3...:并入字段以怎样的数据内容录入新维度字段
AS VAL部分可以不写,最终会以TB.COL作为数据内容录入 */       
--代码:
SELECT * FROM SCORE_2 UNPIVOT(COURSE FOR SCORE IN (CHINESE,MATH,ENGLISH));

注意:有的数据库并没有PIVOT和UNPIVOT这两个专用函数,所以我们一般做行列转换用的还是 CASE WHEN 和 UNION ALL 比较多。;
===============================================================

行列转换练习:
行转列
select student,'chinese' course,chinese from score_2
union
select student,'math' course,math from score_2
union
select student,'english' course,english from score_2;

列转行
select student,sum(case when course='CHINESE' THEN score ELSE 0 END) CHINESE,
               sum(case when course='MATH' THEN score ELSE 0 END) MATH,
               sum(case when course='ENGLISH' THEN score ELSE 0 END) ENGLISH
from score_1 Group by student;

SELECT * FROM SCORE_2;  
SELECT * FROM SCORE_1;

select * from score_1 pivot(sum(score) for course in ('CHINESE' as CHINESE,'ENGLISH' as ENGLISH,'MATH' as MATH));
select * from score_1 pivot(max(score) for course in ('CHINESE','ENGLISH','MATH'))
SELECT * FROM SCORE_2 UNPIVOT(SCORE FOR COURSE IN (CHINESE,ENGLISH,MATH));















 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值