开窗函数的使用详解(窗口范围ROWS与RANGE详解)

本文详细解析了SQL中开窗函数的ROWS和RANGE子句,阐述了它们的构成、区别以及在实际场景中的应用,包括计算部门工资总额、累计销售额和销售排名等案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、函数写法

函数名(参数) OVER (PARTITION BY子句 ORDER BY子句 ROWS/RANGE子句)

由三部分组成: 函数名:如sum、max、min、count、avg等聚合函数以及lead、lag行比较函数等; over:
关键字,表示前面的函数是分析函数,不是普通的集合函数; 分组子句:over关键字后面挂号内的内容;

分析子句又由下面三部分组成: PARTITION BY :分组子句,表示分析函数的计算范围,不同的组互不相干; ORDER BY:
排序子句,表示分组后,组内的排序方式; ROWS/RANGE:窗口子句,是在分组(PARTITION
BY)后,组内的子分组(也称窗口),此时分析函数的计算范围窗口,而不是PARTITON。窗口有两种,ROWS和RANGE;

             

  1. PARTITION BY 子句

    • 这是可选的。
    • 它用于将数据集分成不同的分区,每个分区可以有自己的窗口函数计算。
    • 例如,如果你有一个按部门分组的员工列表,并想为每个部门的员工分配一个序号,你可以使用 PARTITION BY 来指定部门。
  2. ORDER BY 子句

    • 这是必需的。
    • 它定义了在窗口函数应用之前,数据应如何排序。
    • 你可以根据一个或多个列来排序。例如,你可以根据员工的入职日期来排序。
  3. ROWS/RANGE 子句

    • 这是定义窗口函数计算的行范围的参数。
    • ROWS:指定一个明确的行数范围。例如,你可以指定从当前行开始并包括之前的5行。
    • RANGE:基于列值来定义范围。例如,你可以指定从当前行开始并包括到相同列值的最后一行。

开窗函数中的ROWS和RANGE子句用于定义窗口的范围,即函数将在哪些行上执行计算。这两个子句有一些关键的区别:

  1. ROWS子句

    • ROWS子句定义了一个明确的行数范围,它基于当前行来指定范围的开始和结束。
    • 范围的大小是固定的,并且与当前行无关。
    • 当你使用ROWS子句时,通常会使用诸如“UNBOUNDED PRECEDING”和“CURRENT ROW”之类的值来定义范围的开始和结束。例如,如果你指定“ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW”,则函数将在从第一行到当前行的所有行上执行计算。
  2. RANGE子句

    • RANGE子句基于列值来定义范围。
    • 范围的大小是动态的,并基于当前行的值来调整。
    • 当使用RANGE子句时,通常会使用诸如“CURRENT ROW”之类的值来定义范围的开始,而范围的结束是基于列值的。例如,如果你指定“RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING”,则函数将在从当前行到结果集末尾的所有行上执行计算,其中每行的范围基于列值来定义。

总结

  • ROWS子句定义了一个基于行数的固定范围,而RANGE子句则基于列值来定义动态范围。
  • 在使用ROWS子句时,你需要指定范围的开始和结束行号。而在使用RANGE子句时,你需要指定范围的开始行号和结束列值。
  • 根据你的数据和需求,你可以选择适当的子句来执行所需的窗口函数计算。

以下详细的描述并且准确地解释了SQL中开窗函数中的ROWS和RANGE子句及其用法。

1. current row:当前行。
2. unbounded:表示无限的范围,例如在排序中表示从最前面或最后面的记录开始。
3. unbounded preceding:表示区间的第一行,通常与聚合函数一起使用,如计算总和或平均值。
4. unbounded following:表示区间的最后一行,常用于分组的结尾部分。
5. unbounded preceding and unbounded following:针对当前所有记录的前一条、后一条记录,分组中的所有记录。
6. preceding:在之前的行,n preceding:当前行之前的n行。
7. following:在之后的行,n following:当前行之后的n行。
8. rows between:用于定义一个明确的行数范围,如“rows between unbounded preceding and current row”表示从第一行到当前行的数据。
9. range between:基于列值的范围,如“range between current row and 350 following”表示从当前行到当前行数据+350的范围内的数据。
10. range between preceding and following:定义一个基于列值的动态范围,如“range between 5 preceding and 5 following”表示当前行数据幅度减5加5后的范围内的数据。

以下是一些实际性的案例,展示了如何使用开窗函数的ROWS和RANGE子句:

  1. 案例一:计算每个部门的员工工资总额

假设有一个名为"employees"的表,其中包含员工的信息和工资。现在要计算每个部门的员工工资总额。

SELECT department,
name,
salary,
SUM(salary) OVER (PARTITION BY department) as total_salary
FROM employees;

在这个例子中,我们使用PARTITION BY子句将数据分成不同的部门,然后使用SUM函数计算每个部门的员工工资总额。通过将SUM函数与OVER子句结合使用,我们可以轻松地计算每个部门的工资总额。


2. 案例二:计算每个员工的累计销售额

假设有一个名为"sales"的表,其中包含销售数据和销售人员的名字。现在要计算每个销售人员的累计销售额。

SELECT name,
sale_date,
sale_amount,
SUM(sale_amount) OVER (PARTITION BY name ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as cumulative_sales
FROM sales;

在这个例子中,我们使用PARTITION BY子句按销售人员名字分组数据,并使用ORDER BY子句按销售日期排序。然后,我们使用SUM函数计算每个销售人员的累计销售额,通过指定ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW来定义窗口范围,包括从第一行到当前行的所有行。


3. 案例三:计算每个员工的销售排名

假设有一个名为"sales"的表,其中包含销售数据和销售人员的名字。现在要计算每个销售人员的销售排名。

SELECT name,
sale_amount,
RANK() OVER (ORDER BY sale_amount DESC) as sales_rank
FROM sales;

在这个例子中,我们使用RANK函数计算每个销售人员的销售排名。通过指定ORDER BY子句按销售金额降序排序,RANK函数将为每个销售人员分配一个排名值。使用OVER子句定义窗口范围,以便RANK函数在整个结果集上执行计算。

窗口函数中的窗口范围可以使用ROWSRANGE两种方式进行定义。在使用RANGE方式时,窗口范围是基于值的范围进行定义的。具体来说,RANGE子句可以指定一个范围,例如指定从当前行开始的前后几行,或者指定一个数值范围。这样,窗口函数将在这个范围内进行计算。\[2\] 需要注意的是,RANGE方式在计算窗口函数时,会考虑值的大小而不是行的物理位置。因此,如果有多个行具有相同的值,它们将被视为同一范围内的行。这使用ROWS方式定义窗口范围时的行数不同。\[2\] 总结来说,窗口函数中的RANGE方式可以根据值的范围来定义窗口范围,而不是基于行的物理位置。这样可以更灵活地进行窗口函数的计算。\[2\] #### 引用[.reference_title] - *1* *2* [MYSQL窗口函数Rows & Range)——滑动窗口函数用法](https://blog.csdn.net/WHYbeHERE/article/details/127896098)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [开窗函数使用详解(窗口范围ROWSRANGE图文详解)](https://blog.csdn.net/m0_52606060/article/details/129132985)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值