SELECT ENAME,SAL,MAX(SAL) OVER(PARTITIONBY DEPTNO) "MAX_SAL" FROM EMP;
相当于字段,可以取别名。
聚合函数和窗口函数的==区别==:
1.聚合函数针对一组数据时只会返回一个值,窗口函数针对一组数据会返回相同数量的值。
2.聚合函数分组的关键词为GROUP BY,窗口函数分组的关键词为PARTITION BY
1 2 3 4 5 6 7 8 9 10
1.查询每个部门的最高薪资 SELECTMAX(SAL) FROM EMP GROUPBY DEPTNO; 2.查询每个部门最高工资员工的姓名和薪资 SELECT ENAME,SAL FROM EMP WHERE SAL IN (SELECTMAX(SAL) FROM EMP GROUPBY DEPTNO) ; SELECT ENAME,SAL FROM EMP WHERE SAL IN (SELECTMAX(SAL) FROM EMP GROUPBY DEPTNO) GROUPBY ENAME,SAL ; SELECT*FROM EMP FORUPDATE; SELECT ENAME,SAL FROM EMP WHERE (SAL,DEPTNO) IN (SELECTMAX(SAL),DEPTNO FROM EMP GROUPBY DEPTNO) ; 3.查询每个员工的姓名和薪资,以及对应部门的最高薪资 SELECT ENAME,SAL,MAX(SAL) FROM EMP GROUPBY ENAME,SAL SELECT ENAME,SAL , MAX_SAL FROM EMP A JOIN (SELECT DEPTNO,MAX(SAL) MAX_SAL FROM EMP GROUPBY DEPTNO) B USING(DEPTNO);
1 2 3 4 5 6 7
SELECT ENAME,SAL,MIN(SAL)OVER (PARTITIONBY DEPTNO) MAX_SAL FROM EMP;
SELECT ENAME,SAL,AVG(SAL)OVER (PARTITIONBY DEPTNO) MAX_SAL FROM EMP;
SELECT ENAME,SAL,SUM(SAL)OVER (PARTITIONBY DEPTNO) MAX_SAL FROM EMP;
SELECT ENAME,SAL,COUNT(SAL)OVER (PARTITIONBY DEPTNO) MAX_SAL FROM EMP;
什么时候会用到窗口函数
当只要求输出聚合函数的值,只需要用到分组(GROUP BY ),如果这种时候用开窗函数,会得到14个值,有点多余。
当每个人需要自己对应部门的聚合函数的值,如果只用GROUP BY ,是以个人为一个组,得不到自己想要的值,可以用表连接,但是用窗口函数会很方便
查询每个部门的最高薪资 SELECTMAX(SAL) FROM EMP GROUPBY DEPTNO;
查询SMITH所在部门的最高薪资的员工信息 SELECT DEPTNO FROM EMP WHERE ENAME ='SMITH'; SELECTMAX(SAL) FROM EMP WHERE DEPTNO IN(SELECT DEPTNO FROM EMP WHERE ENAME ='SMITH'); SELECT*FROM EMP WHERE (DEPTNO,SAL) IN (SELECT DEPTNO,MAX(SAL) FROM EMP WHERE DEPTNO IN(SELECT DEPTNO FROM EMP WHERE ENAME ='SMITH') GROUPBY DEPTNO);--单行多列
查询每个部门最高工资的员工姓名和工资 SELECTMAX(SAL) FROM EMP GROUPBY DEPTNO ; SELECT ENAME ,SAL FROM EMP WHERE (DEPTNO,SAL) IN(SELECT DEPTNO,MAX(SAL) FROM EMP GROUPBY DEPTNO);--多行多列
查询每个员工的姓名和工资,以及对应部门的最高工资 SELECT ENAME,SAL FROM EMP; SELECT DEPTNO,MAX(SAL) FROM EMP GROUPBY DEPTNO;
SELECT*FROM (SELECT DEPTNO,ENAME,SAL FROM EMP) A JOIN (SELECT DEPTNO,MAX(SAL) FROM EMP GROUPBY DEPTNO) B USING(DEPTNO);
SELECT ENAME,SAL,MAX_SAL FROM EMP A JOIN (SELECT DEPTNO,MAX(SAL) MAX_SAL FROM EMP GROUPBY DEPTNO) B ON A.DEPTNO=B.DEPTNO;
1.聚合函数类
语法:SELECT 聚合函数(字段)OVER(分析子句) FROM 表;
分析子句里面有分组和排序 之前学的分组关键词:GROUP BY 之前学的排序关键词:ORDER BY 窗口函数的分组关键词:PARTITION BY 窗口函数的排序关键词:ORDER BY
写在SELECT后面,相当于一个字段,可以取别名
1 2 3 4 5 6 7 8 9 10
查询每个员工的姓名和工资,以及对应部门的最高工资 SELECT ENAME,SAL,DEPTNO,MAX(SAL)OVER(PARTITIONBY DEPTNO) R FROM EMP;--对应每个部门的最高工资
SELECT ENAME,SAL,DEPTNO,MIN(SAL)OVER(PARTITIONBY DEPTNO) FROM EMP;--对应每个部门的最低工资
SELECT ENAME,SAL,DEPTNO,SUM(SAL)OVER(PARTITIONBY DEPTNO) FROM EMP;--对应每个部门的总计工资
SELECT ENAME,SAL,DEPTNO,AVG(SAL)OVER(PARTITIONBY DEPTNO) FROM EMP;--对应每个部门的平均工资
SELECT ENAME,SAL,DEPTNO,COUNT(SAL)OVER(PARTITIONBY DEPTNO) FROM EMP;--对应每个部门的人数
窗口函数和聚合函数的区别 1.当聚合函数针对一组数据进行分析时,只会返回一个值;窗口函数针对一组数据进行分析时,会返回相应数量的值; 2.聚合函数的分组关键词为GROUP BY ,窗口函数的分组关键词为PARTITION BY
窗口函数属于–OLAP(联机分析处理),主要是进行复杂的分析操作,提供直观易懂的查询结果 窗口可以理解为一个范围,以PARTITION BY 为例,分组后的结果就可以理解为窗口 OLTP(联机事务处理),主要进行简单的数据增删改查。
--窗口函数中使用ORDER BY ,可以理解为从第一行到当前行 SELECT ENAME,SAL,DEPTNO,MAX(SAL)OVER(ORDERBY SAL) FROM EMP;--对应从第一行到当前行的最高工资 SELECT ENAME,SAL,DEPTNO,MAX(SAL)OVER(ORDERBY SAL DESC) FROM EMP;--对应从第一行到当前行的最高工资
SELECT ENAME,SAL,DEPTNO,MIN(SAL)OVER(ORDERBY SAL) FROM EMP;--对应从第一行到当前行的最低工资 SELECT ENAME,SAL,DEPTNO,MIN(SAL)OVER(ORDERBY SAL DESC) FROM EMP;--对应从第一行到当前行的最低工资
SELECT ENAME,SAL,DEPTNO,SUM(SAL)OVER(ORDERBY SAL) FROM EMP;--对应从第一行到当前行的累计工资
SELECT ENAME,SAL,DEPTNO,AVG(SAL)OVER(ORDERBY SAL) FROM EMP;----对应从第一行到当前行的平均工资
SELECT ENAME,SAL,DEPTNO,COUNT(SAL)OVER(ORDERBY SAL) FROM EMP;----对应从第一行到当前行的人数(会并列,前面会跳级)
窗口函数的分析子句中可以只写分组和排序中的一个,也可以全部都写 SELECT ENAME,SAL,DEPTNO,MAX(SAL)OVER(PARTITIONBY DEPTNO ORDERBY SAL) FROM EMP;--对应部门的从第一行到当前行的最高工资 SELECT ENAME,SAL,DEPTNO,MAX(SAL)OVER(PARTITIONBY DEPTNO ORDERBY SAL DESC) FROM EMP;--对应部门从第一行到当前行的最高工资
SELECT ENAME,SAL,DEPTNO,MIN(SAL)OVER(PARTITIONBY DEPTNO ORDERBY SAL) FROM EMP;--对应部门的从第一行到当前行的最低工资 SELECT ENAME,SAL,DEPTNO,MIN(SAL)OVER(PARTITIONBY DEPTNO ORDERBY SAL DESC) FROM EMP;--对应从第一行到当前行的最低工资
SELECT ENAME,SAL,DEPTNO,SUM(SAL)OVER(PARTITIONBY DEPTNO ORDERBY SAL) FROM EMP;--对应部门的从第一行到当前行的累计工资
SELECT ENAME,SAL,DEPTNO,AVG(SAL)OVER(PARTITIONBY DEPTNO ORDERBY SAL) FROM EMP;----对应部门的从第一行到当前行的平均工资
SELECT ENAME,SAL,DEPTNO,COUNT(SAL)OVER(PARTITIONBY DEPTNO ORDERBY SAL) O_SAL FROM EMP;----对应部门的从第一行到当前行的人数(会并列,会跳级)
注意: 1.PARTITION BY 能放在ORDER BY 后面吗? –不可以 2.当分析子句同时含有分组和排序时,同时包含他们两个的特点。 3.能不能在一个SELECT 语句中出现多个窗口函数呢? –可以
查询工资从小到大不算并列在第四位到第八位的员工信息 select*from(select a.*,rownum b from emp a orderby sal) b where b between4and8;--错误 select*from(select a.*,rownum 排序 from(select*from emp orderby sal) a) where 排序 between4and8; SELECT*FROM (SELECT A.*,ROWNUM 排序 FROM (SELECT*FROM EMP ORDERBY SAL DESC)A) WHERE 排序 BETWEEN4AND8; --是降序,应该为升序
SELECT*FROM (SELECT ENAME ,SAL,ROW_NUMBER()OVER(ORDERBY SAL) R FROM EMP) where R BETWEEN4AND8 ;
SELECT ENAME,SAL,DEPTNO,COUNT(SAL)OVER( ORDERBY SAL DESC) FROM EMP;-- 1 2 3 5 5 6 SELECT ENAME,SAL,DEPTNO,COUNT(SAL)OVER( ORDERBY SAL ) FROM EMP ORDERBY SAL DESC;
问:查询每个部门薪资排在第二名的员工信息(要求考虑重复数据,不跳级) SELECT*FROM (SELECT A.*,DENSE_RANK()OVER(PARTITIONBY DEPTNO ORDERBY SAL DESC) R FROM EMP A) WHERE R =2;
查询每个部门薪资排在第一名的员工信息 SELECT*FROM (SELECT A.*,DENSE_RANK()OVER(PARTITIONBY DEPTNO ORDERBY SAL DESC) R FROM EMP A) WHERE R =1;--四条数据
SELECT*FROM (SELECT A.*,RANK()OVER(PARTITIONBY DEPTNO ORDERBY SAL DESC) R FROM EMP A) WHERE R =1;--四条数据
SELECT*FROM (SELECT A.*,ROW_NUMBER()OVER(PARTITIONBY DEPTNO ORDERBY SAL DESC) R FROM EMP A) WHERE R =1;--三条数据
表连接的内容: 条件写在WHERE和ON后面的区别 1.名字不一样 2.所属不一样,ON跟在FROM子句,WHERE属于WHERE子句 3.SELECT * FROM EMP A LEFT JOIN DEPT B ON A.DEPTNO = B.DEPTNO AND A.DEPTNO =10; –条件写在ON后面,是先对表进行数据筛查,再以筛查结果作为一个新的数据源进行表连接 –条件写在WHERE后面,先进行表连接,再进行条件筛查
SELECT ENAME,SAL,MAX(SAL)OVER(ORDERBY SAL ) FROM EMP;
SELECT ENAME,SAL,MAX(SAL)OVER(PARTITIONBY DEPTNO ORDERBY SAL ROWSBETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM EMP; --每个组在第一行到最后一行这个范围中选最大值
3.从当前行到当前行的后2行 ROWSBETWEENCURRENTROWAND 2 FOLLOWING
1 2 3 4 5 6 7
SELECT ENAME,SAL,MAX(SAL)OVER(ORDERBY SAL ) FROM EMP;
SELECT ENAME,SAL,MAX(SAL)OVER( ORDERBY SAL ROWSBETWEENCURRENTROWAND2 FOLLOWING) FROM EMP; --从当前行到当前行的后2行中找最大值
SELECT ENAME,SAL,MIN(SAL)OVER( ORDERBY SAL ROWSBETWEEN1PRECEDING AND2 FOLLOWING) FROM EMP; --从当前行的前1行到当前行的后2行中找最小值
1 2 3 4
思考题:按照工资升序排序,输出姓名,工资,以及每人工资前一行和工资后两行;(两种方法) SELECT ENAME,SAL,MAX(SAL)OVER(ORDERBY SAL ROWSBETWEEN1 PRECEDING AND1 PRECEDING),MAX(SAL)OVER(ORDERBY SAL ROWSBETWEEN2 FOLLOWING AND2 FOLLOWING) FROM EMP;
SELECT ENAME,SAL,LAG(SAL,1)OVER(ORDERBY SAL),LEAD(SAL,2)OVER(ORDERBY SAL) FROM EMP;