SQL开发知识:SQL Server 开窗函数 Over()代替游标的使用详解

1. SQL Server开窗函数 Over()的概念

SQL Server中的开窗函数(Over)是一种高级的SQL语言特性,它可以帮助开发人员避免使用游标等复杂和低效的代码构造,实现更为简捷、高效的数据分析和统计操作。

在日常开发过程中,我们经常需要对数据进行一些聚合或者排序操作,比如对一张订单表进行按照日期、客户id进行分组汇总,或者对一张商品销售表按照销售数量进行排名或者销售累计百分比等等。使用传统的 SQL 语法,我们可以使用GROUP BY、HAVING、ORDER BY 等关键字来实现这些操作,而使用 Over 函数,我们可以更为便捷地完成这些任务,特别是当我们遇到复杂的需求时,Over 函数比传统语法更加简单、易于扩展。

2. SQL Server开窗函数 Over()的使用方法

2.1 基本的语法结构

Over 函数通常会结合聚合函数一起使用,下面是SQL Server中常见的 Over 函数的语法结构:

SELECT

function () OVER ( [PARTITION BY partition_expression, ……] [ORDER BY order_expression [ASC/DESC], ……]

[ROWS/RANGE clause] )

FROM

table_name;

从上面的语法可以看出,Over 函数有以下几个要素:

聚合函数function: 必须指定一个聚合函数(如SUM、AVG、COUNT、MAX、MIN、NTILE等) ,以便统计分组

PARTITION BY partition_expression:可选,表示按多个字段分组

ORDER BY order_expression [ASC/DESC]:可选,表示排序时使用的字段

ROWS/RANGE clause:可选,用来控制 Over 函数统计时处理的行或范围(ROWS表示行、RANGE表示值),默认为 RANGE UNBOUNDED PRECEDING AND CURRENT ROW。 具体讲解见下文。

2.2 如何使用 Partition By 子句

Partition By 是 Over 函数最重要的部分之一,它主要的作用是按照多个字段对数据进行分组。 大部分情况下我们需要对数据进行分组,而 Partition By 子句正是为此提供了便利。

下面是一个使用 Partition By 子句的例子:

SELECT department, SUM(salary) OVER(PARTITION BY department) as dept_salary

FROM employee_salaries;

上面的SQL语句可以将 employee_salaries 表中的数据按照 department 分组,并计算出每个部门的薪资总和(dept_salary)。

2.3 如何使用 Order By 子句

在使用 Over 函数的时候,通过使用 Order By 子句可以指定数据的排序方式,从而准确地达到预期的计算效果。下面是一个使用 Order By 子句的例子:

SELECT department, SUM(salary) OVER(PARTITION BY department ORDER BY salary DESC) as dept_salary

FROM employee_salaries;

上面的SQL语句可以将 employee_salaries 表中的数据按照 department 分组,并按照 salary 字段降序排列。对每一个分组求和,计算结果为每个部门的薪资等级。

2.4 如何使用 Rows/RANGE 子句

使用 ROWS/RANGE 子句可以非常精确地指定 Over 函数是如何对窗口中的数据进行操作的,在 Over 函数的使用当中,这个子句通常是可选的。

第一个关键字确定 Over 函数的计算方式。ROWS 子句,数据的计算是按照行号(行数)的偏移量确定的。RANGE 子句数据的计算则是按照属性值的偏移量确定的。

1)ROWS 子句:

SELECT name, score,

AVG(score) OVER(PARTITION BY name ORDER BY score ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) as moving_average

FROM test_table;

上面的SQL语句可以实现test_table表中每个名字的分数移动平均数的计算。相当于对当前行的上下两行和下下行的分数进行平均计算。

2)RANGE 子句:

SELECT name, score,

AVG(score) OVER(PARTITION BY name ORDER BY score RANGE BETWEEN 50 PRECEDING AND 50 FOLLOWING) as percentile_rank

FROM test_table;

上面的SQL语句可以实现对test_table表中每个名字的百分排名的计算。相当于对当前行的±50%分数值进行了排名的计算。

3. Over 函数与游标的比较

在SQL Server中,游标(CURSOR)是一种非常直观而且容易理解的方式,通过它我们可以一行一行地遍历表的每一行数据,对其进行一些复杂的处理。游标的使用虽然便捷易操作,但是它的缺点也非常明显,那就是效率比较低,而且易于造成内存溢出,难以适应大数据量、高并发的应用场景。

相比之下,使用 Over 函数可以提高SQL语句的执行效率,大大降低 SQL Server 对存储和计算资源的消耗。在进行数据查询、过滤、排序等操作时,Over 函数的效率要比游标高不少。值得一提的是,使用 Over 函数的代码更加简洁、易于理解,我们可以看到,它的使用已经成为了一种主流趋势。

4. 总结

本文主要介绍了SQL Server中 Over 函数在数据分析和统计上的处理技巧以及语法。使用 Over 函数时进行分组、排序、计算等操作,不仅操作简单快速,而且代码更加符合规范、易读易懂,因此在实际应用开发中越来越得到广泛的应用。在使用 Over 函数的时候,还需要灵活运用 ROW 和 RANGE 子句来控制窗口中计算的数据,这样可以更加准确地达到我们预期的目标。

数据库标签