📜  SQL 中的窗口函数

📅  最后修改于: 2022-05-13 01:54:47.039000             🧑  作者: Mango

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(),称为聚合窗口函数。

考虑以下员工表:

NameAgeDepartmentSalary
Ramesh20Finance50, 000
Deep25Sales30, 000
Suresh22Finance50000
Ram28Finance20, 000
Pradeep22Sales20, 000

例子 -
查找每个部门的员工平均工资,并按年龄对部门内的员工进行排序。

SELECT Name, Age, Department, Salary, 
 AVERAGE(Salary) OVER( PARTITION BY Department ORDER BY Age) AS Avg_Salary
 FROM employee

上述查询的输出将是:

NameAgeDepartmentSalaryAvg_Salary
Ramesh20Finance50, 00040, 000
Suresh22Finance5000040, 000
Ram28Finance20, 00040, 000
Pradeep22Sales20, 00025, 000
Deep25Sales30, 00025, 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_noNameDepartmentSalaryemp_rankemp_dense_rank
1SureshFinance50, 00011
2RameshFinance50, 00011
3RamFinance20, 00032
1DeepSales30, 00011
2PradeepSales20, 00022

因此,我们可以看到,正如 ROW_NUMBER() 的定义中提到的,行号是每个分区内的连续整数。此外,我们可以看到排名和密集排名之间的差异,在密集排名中排名值之间没有差距,而在重复排名后排名值之间存在差距。