聚合函数,都是统计中都是不包括NULL值的。

唯独,count(*)包括NULL值。(注:count(字段)不包括NULL值。)


开窗函数:

与 聚 合函数一样,开窗函数也是对行集组进行聚合计算,但是它不像普通聚合函数那样

每组只返回一个值,开窗函数可以为每组返回多个值,因为开窗函数所执行聚合计算的行

集组是窗口。在ISO SQL规定了这样的函数为开窗函数,在 Oracle中则被称为分析函数,

而在DB2中则被称为OLAP函数。

开窗函数的调用格式:

函数名(列)OVER(选项)

OVER关键字表示把函数当成开窗函数不是聚合函数。

SQL标准允许将所有聚合函数做成开窗函数,使用OVER关键字来区分这两种用法。

如:开窗函数COUNT(*) OVER()对于查询结果的每一行都返回所有符合条件的行的条数。

OVER关键字后的括号中还经常添加选项用以改变进行聚合运行的窗口范围。如果OVER关键字后的括号中的选项为空,则开窗函数会对结果集中的所有行进行聚合运算。

以上参照,此处链接

分析函数的形式
分析函数带有一个开窗函数over(),包含三个分析子句:分组(partition by), 排序(order by), 窗口(rows) ,他们的使用形式如下:over(partition by xxx order by yyy rows between zzz)。
注:窗口子句在这里我只说rows方式的窗口,range方式和滑动窗口也不提

    

分析函数例子(在scott用户下模拟)

示例目的:显示各部门员工的工资,并附带显示该部分的最高工资。


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句



--显示各部门员工的工资,并附带显示该部分的最高工资。
SELECT E.DEPTNO,
       E.EMPNO,
       E.ENAME,
       E.SAL,
       LAST_VALUE(E.SAL) 
       OVER(PARTITION BY E.DEPTNO 
            ORDER BY E.SAL ROWS 
            --unbounded preceding and unbouned following针对当前所有记录的前一条、后一条记录,也就是表中的所有记录
            --unbounded:不受控制的,无限的
            --preceding:在...之前
            --following:在...之后
            BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) MAX_SAL
  FROM EMP E;



sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句


运行结果:


sql server 可以使用开窗函数吗 sql开窗函数语法_聚合函数_03

               

示例目的:按照deptno分组,然后计算每组值的总和


SELECT EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY ENAME) max_sal
  FROM SCOTT.EMP;


运行结果:


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句_04

     

示例目的:对各部门进行分组,并附带显示第一行至当前行的汇总


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句



SELECT EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       --注意ROWS BETWEEN unbounded preceding AND current row  是指第一行至当前行的汇总
       SUM(SAL) OVER(PARTITION BY DEPTNO 
                     ORDER BY ENAME 
                     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) max_sal
  FROM SCOTT.EMP;



sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句


运行结果:


sql server 可以使用开窗函数吗 sql开窗函数语法_聚合函数_07

   

示例目标:当前行至最后一行的汇总


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句



SELECT EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       --注意ROWS BETWEEN current row AND unbounded following 指当前行到最后一行的汇总
       SUM(SAL) OVER(PARTITION BY DEPTNO 
                     ORDER BY ENAME 
                     ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) max_sal
  FROM SCOTT.EMP;



sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句


运行结果:


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句_10

   

 示例目标:当前行的上一行(rownum-1)到当前行的汇总


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句



SELECT EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       --注意ROWS BETWEEN 1 preceding AND current row 是指当前行的上一行(rownum-1)到当前行的汇总 
       SUM(SAL) OVER(PARTITION BY DEPTNO 
                     ORDER BY ENAME ROWS 
                     BETWEEN 1 PRECEDING AND CURRENT ROW) max_sal
  FROM SCOTT.EMP;



sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句


运行结果:


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句_13

    

示例目标:   当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总     


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句



SELECT EMPNO,
       ENAME,
       DEPTNO,
       SAL,
       --注意ROWS BETWEEN 1 preceding AND 1 following 是指当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总
       SUM(SAL) OVER(PARTITION BY DEPTNO 
                     ORDER BY ENAME 
                     ROWS BETWEEN 1 PRECEDING AND 2 FOLLOWING) max_sal
  FROM SCOTT.EMP;



sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句


运行结果:


sql server 可以使用开窗函数吗 sql开窗函数语法_sql语句_16

      



二、理解over()函数

1.1、两个order by的执行时机
分析函数(以及与其配合的开窗函数over())是在整个sql查询结束后(sql语句中的order by的执行比较特殊)再进行的操作, 也就是说sql语句中的order by也会影响分析函数的执行结果:

开窗函数over()中的order by子句里的内容一样,

那么sql语句中的排序将先执行,分析函数在分析时就不必再排序;
b) 两者不一致:如果sql语句中的order by不满足与分析函数配合的开窗函数over()分析时要求的排序,即sql语句中的order by子句里的内容和开窗函数over()中的order by子句里的内容不一样,

那么sql语句中的排序将最后在分析函数分析结束后执行排序。

           

1.2、开窗函数over()分析函数中的分组/排序/窗口
      开窗函数over()分析函数
包含三个分析子句:分组子句(partition by), 排序子句(order by), 窗口子句(rows)
      窗口就是分析函数分析时要处理的数据范围,就拿sum来说,它是sum窗口中的记录而不是整个分组中的记录,因此我们在想得到某个栏位的累计值时,我们需要把窗口指定到该分组中的第一行数据到当前行, 如果你指定该窗口从该分组中的第一行到最后一行,那么该组中的每一个sum值都会一样,即整个组的总和。

      窗口子句在这里我只说rows方式的窗口,range方式和滑动窗口也不提。

      窗口子句中我们经常用到指定第一行,当前行,最后一行这样的三个属性:
第一行是 unbounded preceding,
当前行是 current row,
最后一行是 unbounded following,

注释:

开窗函数over()出现分组(partition by)子句时,

unbounded preceding即第一行是指表中一个分组里的第一行, unbounded following即最后一行是指表中一个分组里的最后一行;

开窗函数over()省略了分组(partition by)子句时, 

unbounded preceding即第一行是指表中的第一行, unbounded following即最后一行是指表中的最后一行。


窗口子句不能单独出现,必须有order by子句时才能出现

例如:


last_value(sal) over(partition by deptno 
                     order by sal 
                     rows between unbounded preceding and unbounded following)


而出现order by子句的时候,不一定要有窗口子句,但效果会很不一样,此时的窗口默认是当前组的第一行到当前行!

如果省略分组,则把全部记录当成一个组。
a) 如果存在order by则默认窗口是unbounded preceding and current row   --当前组的第一行到当前行
b) 如果这时省略order by则窗口默认为unbounded preceding and unbounded following  --整个组
 

而无论是否省略分组子句,如下结论都是成立的:

1、窗口子句不能单独出现,必须有order by子句时才能出现

2、当省略窗口子句时:
a) 如果存在order by则默认的窗口是unbounded preceding and current row  --当前组的第一行到当前行,即在当前组中,第一行到当前行
b) 如果同时省略order by则默认的窗口是unbounded preceding and unbounded following  --整个组

              
所以,


lag(sal) over(order by sal) 解释

over(order by salary)表示意义如下:

首先,我们要知道由于省略分组子句,所以当前组的范围为整个表的数据行,

然后,在当前组(此时为整个表的数据行)这个范围里执行排序(即order by salary),

最后,我们知道分析函数lag(sal)在当前组(此时为整个表的数据行)这个范围里的窗口范围为当前组的第一行到当前行,即分析函数lag(sal)在这个窗口范围执行。