SQL 中的窗口函数
窗口函数在特定窗口(行集)上应用聚合和排名函数。 OVER 子句与窗口函数一起使用来定义该窗口。 OVER 子句做了两件事:
- 将行划分为一组行。 (使用了 PARTITION BY 子句)
- 将这些分区中的行按特定顺序排列。 (使用 ORDER BY 子句)
笔记 -
如果未完成分区,则 ORDER BY 对表的所有行进行排序。
基本语法:
SELECT coulmn_name1,
window_function(cloumn_name2),
OVER([PARTITION BY column_name1] [ORDER BY column_name3]) AS new_column
FROM table_name;
window_function= any aggregate or ranking function
column_name1= column to be selected
coulmn_name2= column on which window function is to be applied
column_name3= column on whose basis partition of rows is to be done
new_column= Name of new column
table_name= Name of table
聚合窗口函数:
应用于特定窗口(行集)的各种聚合函数,例如 SUM()、COUNT()、AVERAGE()、MAX()、MIN(),称为聚合窗口函数。
考虑以下员工表:
Name | Age | Department | Salary |
---|---|---|---|
Ramesh | 20 | Finance | 50, 000 |
Deep | 25 | Sales | 30, 000 |
Suresh | 22 | Finance | 50000 |
Ram | 28 | Finance | 20, 000 |
Pradeep | 22 | Sales | 20, 000 |
例子 -
查找每个部门的员工平均工资,并按年龄对部门内的员工进行排序。
SELECT Name, Age, Department, Salary,
AVERAGE(Salary) OVER( PARTITION BY Department ORDER BY Age) AS Avg_Salary
FROM employee
上述查询的输出将是:Name Age Department Salary Avg_Salary Ramesh 20 Finance 50, 000 40, 000 Suresh 22 Finance 50000 40, 000 Ram 28 Finance 20, 000 40, 000 Pradeep 22 Sales 20, 000 25, 000 Deep 25 Sales 30, 000 25, 0000
正如我们在上面的例子中看到的,每个部门的平均工资被计算并显示在 Avg_Salary 列中。此外,特定列中的员工按年龄排序。
排名窗口函数:
排名函数有,RANK()、DENSE_RANK()、ROW_NUMBER()
- 排名() -
顾名思义,rank函数为每个分区中的所有行分配排名。排名被分配,使得第一行的排名 1 和具有相同值的行被分配相同的排名。对于两个相同排名值之后的下一个排名,将跳过一个排名值。 - DENSE_RANK() –
它为分区内的每一行分配排名。就像排名函数第一行被分配排名 1 并且具有相同值的行具有相同的排名。 RANK() 和 DENSE_RANK() 的区别在于,在 DENSE_RANK() 中,对于两个相同 rank 之后的下一个 rank,使用连续整数,不跳过任何 rank。 - ROW_NUMBER() –
它将连续整数分配给分区内的所有行。在一个分区内,没有两行可以有相同的行号。
笔记 -
ORDER BY() 应在使用排名窗口函数时强制指定。
例子 -
根据各部门内的工资计算员工的行号、职级、密集职级为员工表。
SELECT
ROW_NUMBER() OVER (PARTITION BY Department ORDER BY Salary DESC)
AS emp_row_no, Name, Department, Salary,
RANK() OVER(PARTITION BY Department
ORDER BY Salary DESC) AS emp_rank,
DENSE_RANK() OVER(PARTITION BY Department
ORDER BY Salary DESC)
AS emp_dense_rank,
FROM employee
上述查询的输出将是:emp_row_no Name Department Salary emp_rank emp_dense_rank 1 Suresh Finance 50, 000 1 1 2 Ramesh Finance 50, 000 1 1 3 Ram Finance 20, 000 3 2 1 Deep Sales 30, 000 1 1 2 Pradeep Sales 20, 000 2 2
因此,我们可以看到,正如 ROW_NUMBER() 的定义中提到的,行号是每个分区内的连续整数。此外,我们可以看到排名和密集排名之间的差异,在密集排名中排名值之间没有差距,而在重复排名后排名值之间存在差距。