SQL SEVER 开窗函数总结

作为一名刚刚入门的开发人员,要学的东西很多很多,有些无从下手。秉着“问题是病、技术是药、对症下药”的原则,将工作中遇到的问题所需的技术进行梳理、归纳和总结。

一、什么是开窗函数

首先,什么是开窗函数,与聚合函数一样,开窗函数也是对行集组进行聚合计算,但是它不像普通聚合函数那样每组只返回一个值,开窗函数可以为每组返回多个值,因为开窗函数所执行聚合计算的行集组是窗口(这里的窗口是指运算将要操作的行的集合)。在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成。下面举例说明:

SQL SEVER 开窗函数总结

现在有这样的要求:查询成绩在90分以下的学生信息,并在每行显示低于90分的学生总数。

通过使用子查询我们可以得出查询结果,代码如下:

SELECT  NAME ,
AGE ,
SCORES ,
( SELECT COUNT(NAME)
FROM Table_1
WHERE SCORES <
)
FROM Table_1
WHERE SCORES < ;

虽然使用子查询能够解决这个问题,但是当数据结构很复杂时,子查询的使用非常麻烦,使用开窗函数则大大简化了查询逻辑,以下代码将展示使用开窗函数得到同样的查询结果:

SELECT  NAME ,
AGE ,
SCORES ,
COUNT(NAME) OVER ( )
FROM Table_1
WHERE SCORES < ;

通过以上例子,我们可以看到使用开窗函数可以解决一些需要通过复杂的相关子查询或者存储过程来实现的查询。与聚合函数不同的是,开窗函数在聚合函数后增加了一个OVER关键字。
开窗函数的调用格式为:函数名(列) OVER(选项)        OVER 关键字表示把函数当成开窗函数而不是聚合函数。SQL  标准允许将所有聚合函数用做开窗函数,使用OVER 关键字来区分这两种用法。


二、开窗函数分类

开窗函数可分为:聚合开窗函数排序开窗函数两种

2.1 聚合开窗函数

在上述例子中,我们所使用的就是聚合开窗函数。OVER关键字后的括号中可以为空,也可以使用 PARTITION BY 子句来定义行的分区来供进行聚合计算。下面的SQL语句使用“AGE”进行分区, 用于查询学生的年龄分布以及相同年龄的学生的个数。

SELECT  DISTINCT
AGE ,
COUNT(NAME) OVER ( PARTITION BY AGE )
FROM Table_1;

  2.2 排序开窗函数

使用较为频繁的排序开窗函数有:ROW_NUMBER(行号)、RANK(排名)、DENSE_RANK(密集排名)和NTILE(分组排名)。

还是上面的例子,现提出如下要求:查询成绩排名第2的学生信息。这里我们就可以使用ROW_NUMBER(行号)函数来实现查询目的。代码如下:

SELECT  *
FROM ( SELECT NAME ,
AGE ,
SCORES ,
ROW_NUMBER() OVER ( ORDER BY SCORES DESC ) AS rownum
FROM Table_1
) T
WHERE T.rownum = ;

  其他排序开窗函数原理与ROW_NUMBER类似,根据不同需求选择使用哪种开窗函数。但是需要注意一点的是,在排序开窗函数中使用PARTITION BY子句需要放置在ORDER BY子句之前。


三、总结

  本文对开窗函数进行了简要介绍,并对如何使用开窗函数进行了说明。正确的使用开窗函数可以有效的提高查询效率,优化查询逻辑,但就像开篇提到的“问题是病、技术是药、对症下药”,只有针对合适的问题使用合适的技术,才能事半功倍。

  

上一篇:Windows环境安装Linux系统及JDK部署


下一篇:AngularJS学习篇(十五)