集合运算
并集(UNION/UNION ALL)
UNION 并集去重
UNION ALL 并集不去重
Union可以对两个或多个结果集进行连接,形成“并集”。子结果集所有的记录组合在一起形成新的结果集。
限定条件:
要是用Union来连接结果集,有4个限定条件。
- 子结果集要具有相同的结构。
- 子结果集的列数必须相同。
- 子结果集对应的数据类型必须可以兼容。
- 每个子结果集不能包含order by子句。
语法格式:
1
| select_statement union [all] select_statement
|
all代表最终的结果集中将包含所有的行,而不能删除重复行。
例子:
1 2 3 4 5
| select * from emp union select * from emp;
SELECT Name FROM Person_1 UNION SELECT Name FROM Person_2;
|
语法:
SELECT 语句
UNION
SELECT 语句
UNION ALL
SELECT 语句
…
1 2 3 4 5 6 7
| SELECT * FROM EMP UNION SELECT * FROM EMP;
SELECT * FROM EMP UNION SELECT * FROM DEPT;
|
1.前后列数得保持一致
2.一列内数据类型得保持一致
1 2 3
| SELECT ENAME FROM EMP UNION SELECT DNAME FROM DEPT;
|
3.结果按照第一列升序排序
1 2 3 4 5 6 7 8 9 10 11
| SELECT DEPTNO FROM EMP UNION SELECT DEPTNO FROM DEPT;
SELECT ENAME,DEPTNO FROM EMP UNION SELECT DNAME,DEPTNO FROM DEPT;
SELECT ENAME ,DEPTNO A FROM EMP UNION SELECT DNAME 部门名称,DEPTNO B FROM DEPT;
|
4.最后结果的列名是按照第一个SELECT语句中的名称确定的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| SELECT ENAME ,DEPTNO A FROM EMP UNION SELECT DNAME 部门名称,LOC B FROM DEPT;
WHERE: 查询姓名为SMITH或者SCOTT的所有员工信息 select * from emp where ename='SMITH' union select * from emp where ename='SCOTT';
select * from emp where ename ='SMITH' union select * from emp where ename='SCOTT';
GROUP BY : select DEPTNO from emp GROUP BY DEPTNO union select DEPTNO from emp GROUP BY SAL,DEPTNO;
select DEPTNO from emp union select DEPTNO from emp GROUP BY SAL,DEPTNO;
ORDER BY : select DEPTNO from emp ORDER BY DEPTNO union select DEPTNO from emp ORDER BY DEPTNO;
select DEPTNO from emp union select DEPTNO from emp ORDER BY DEPTNO DESC;
select DEPTNO from emp ORDER BY DEPTNO union select DEPTNO from emp ;
|
5.ORDER BY 只能放在最后一个语句里面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| SELECT SNAME FROM STUDENT UNION SELECT SNAME FROM STUDENTS ORDER BY SNAME DESC;
select DEPTNO from emp union select EMPNO from emp order by DEPTNO DESC;
SELECT * FROM EMP A JOIN DEPT B ON A.DEPTNO = B.DEPTNO C
select max(sal) A from emp group by deptno union select min(sal) from emp where deptno =20 group by deptno order by A desc ;
SELECT DEPTNO FROM EMP GROUP BY DEPTNO ORDER BY MIN(SAL); SELECT * FROM EMP GROUP BY ORDER BY MAX(SAL);
|
总结:
- 结果会去重
- 列数得保持一致,同一列内数据类型得保持一致
- 列名以第一个SELECT语句为准
- 结果默认以第一列升序排列
- ORDER BY 只能写在最后一个SELECT 语句中
UNION ALL 并集不去重
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| SELECT * FROM EMP UNION ALL SELECT * FROM EMP;
SELECT DEPTNO FROM EMP UNION ALL SELECT DEPTNO FROM EMP;
SELECT DEPTNO FROM EMP UNION ALL SELECT DEPTNO,EMPNO FROM EMP;
SELECT DEPTNO FROM EMP UNION ALL SELECT ENAME FROM EMP;
SELECT DEPTNO FROM EMP UNION ALL SELECT DEPTNO B FROM EMP;
SELECT DEPTNO FROM EMP ORDER BY DEPTNO UNION ALL SELECT DEPTNO FROM EMP ORDER BY DEPTNO;
SELECT 2 FROM EMP UNION SELECT 1 FROM EMP UNION ALL SELECT 3 FROM EMP;
SELECT 1,2 FROM EMP UNION SELECT 2,3 FROM EMP UNION SELECT 2,3 FROM EMP;
SELECT 1,2 FROM EMP UNION (SELECT 2,3 FROM EMP UNION ALL SELECT 2,3 FROM EMP);
|
交集(INTERSECT)
1 2 3
| select ename,sal from emp where sal between 700 and 1300 intersect select ename,sal from emp where sal between 1201 and 1400;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| SELECT DEPTNO FROM EMP INTERSECT SELECT DEPTNO FROM DEPT;
SELECT SAL FROM EMP INTERSECT SELECT SAL FROM EMP;
SELECT 2 FROM EMP INTERSECT SELECT 1 FROM EMP INTERSECT SELECT 3 FROM EMP;
SELECT 1,2 FROM EMP INTERSECT SELECT 2,3 FROM EMP INTERSECT SELECT 2,3 FROM EMP;
SELECT 1,2 FROM EMP INTERSECT (SELECT 2,3 FROM EMP INTERSECT SELECT 2,3 FROM EMP);
|
==总结==:
作用是输出重复的部分,必须得所有的东西都一致才能输出
差集(MINUS)
minus可以对两个或多个结果集进行连接,形成“差集”。返回左边结果集合中已经有的记录,而右边结果集中没有的记录。
==作用==:输出第一个查询语句中独有的内容
限定条件:
1、子结果集要具有相同的结构。
2、子结果集的列数必须相同。
3、子结果集对应的数据类型必须可以兼容。
4、每个子结果集不能包含order by 子句。
语法形式:
1
| select_statement minus select_statement
|
自动删除重复行。
示例:
1 2 3
| SELECT Name FROM Person_1 minus SELECT Name FROM Person_2
|
注意:
1.ORDER BY是对整个运算后的结果排序,并不是对单个数据集。
2.ORDER BY后面排序的字段名称是第一个数据集的字段名或者别名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| SELECT DEPTNO FROM EMP MINUS SELECT DEPTNO FROM DEPT;
SELECT DEPTNO FROM DEPT MINUS SELECT DEPTNO FROM EMP;
SELECT * FROM EMP MINUS SELECT * FROM EMP ;
SELECT EMPNO FROM EMP MINUS SELECT ENAME FROM EMP WHERE DEPTNO = 20 AND ENAME = 'SMITH';
|
补充
当union all和order by 如下一起使用时,会报sql未正确结束
1 2 3 4 5
| select name,age from student order by age
union all
select name,age from person order by age
|
通用的解决方法有三种:
1、将结果集==作为一张临时表==然后查询排序
1 2 3 4 5
| select * from (select name,age from student
union all
select name,age from person order by age) order by age
|
2、单独对表进行排序后
进行并集操作
1 2 3 4 5
| select * from (select name,age from student order by age)
union all
select * from (select name,age from person order by age)
|
3、order by + 字段在结果集中的序号
1 2 3 4 5 6 7
| select name,age from student
union all
select name,age from person
order by 2
|
单查多列+并集运算
PIVOT
将维度数据==拆解==成多个列
—对应 SUM (CASE WHEN …)
1 2 3 4 5 6 7
| SELECT * FROM TB PIVOT(SUM(TB.COL1) FOR TB.COL2 IN (VAL1 AS NEW_COL1, VAL2 AS NWE_COL2, VAL3 AS NEW_COL3) );
|
TIPS:
PIVOT函数一定要有聚合函数 TB.COL1:被聚合分析的字段 TB.COL2:被拆解的字段
VAL1,VAL2,VAL3:TB.COL2字段中的某值 NEW_COL1,NEW_COL2,NEW_COL3: 字段拆解后形成的新字段
AS NEW_COL: 这个部分可不写,不写就以VAL作为字段名展示
UNPIVOT
将多个列==合并==成一个维度
—对应UNION ALL
1 2 3 4 5 6 7
| SELECT * FROM TB UNPIVOT (NEW_COL1 FOR NEW_COL2 IN ( TB.COL1 AS VAL1, TB.COL2 AS VAL2, TB.COL3 AS VAL3) );
|
TIPS:
- UNPIVOT函数不需要聚合函数 NEW_COL1:用来收纳交叉数据的字段,字段名自取 NEW_COL2:新和成的维度字段,名字自取
- TB.COL1,TB.COL2,TB.COL3: 被并入的字段 VAL1,VAL2,VAL3: 并入的字段以怎样的数据内容录入新维度字段
- AS VAL :这个部分可不写 ,不写则以TB.COL的名字作为字段名
==大总结==:
- 所有的集合运算可以反复交叉使用
UNION、INTERSECT、MINUS都会去重,UNION ALL不去重
UNION、INTERSECT、MINUS都会默认以第一列升序排列,UNION ALL不会
有括号的先运行括号里的内容
列名以第一个SELECT语句为准
ORDER BY 只能放在最后一个语句里面
列数必须保持一致,一列内数据类型必须保持一致