MySQL窗口函数

MySQL的窗口函数(也称为分析函数)非常有用,特别是在进行复杂数据分析和处理时。它们能够对数据集的各部分进行计算,而不必改变数据的物理顺序。这里将列举一些常用的窗口函数,并提供具体的SQL代码示例。

窗口函数

1. ROW_NUMBER()

用于为窗口内的每一行分配一个唯一的序号。

SELECT 
  name,
  department,
  salary,
  ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rank
FROM employees;

在这个例子中,ROW_NUMBER() 为每个部门内的员工根据薪水高低分配一个排名。

执行结果

namedepartmentsalaryrank
AliceSales50001
BobSales45002
CarolSales45003
DaveHR30001

说明
在这个结果中,每个部门的员工根据薪水从高到低被赋予一个唯一的序号。即使薪水相同,序号也会递增。

2. RANK()

ROW_NUMBER() 类似,但如果遇到并列,则会跳过下一个序号。

SELECT 
  name,
  department,
  salary,
  RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank
FROM employees;

执行结果

namedepartmentsalaryrank
AliceSales50001
BobSales45002
CarolSales45002
DaveHR30001

说明
ROW_NUMBER()类似,但在薪水并列的情况下,赋予相同的排名,并且下一个排名会跳过。

3. DENSE_RANK()

RANK() 类似,但不跳过任何序号。

SELECT 
  name,
  department,
  salary,
  DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank
FROM employees;

即使有并列,也不会跳过任何排名。

执行结果

namedepartmentsalaryrank
AliceSales50001
BobSales45002
CarolSales45002
DaveHR30001

说明
此函数不会跳过任何排名,即使有并列情况。

4. SUM()

对窗口内的值进行求和。

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

这个例子计算了每个部门所有员工的薪水总和。

执行结果

namedepartmentsalarytotal_salary
AliceSales500014000
BobSales450014000
CarolSales450014000
DaveHR30003000

说明
显示了每个部门的员工薪水总和。

5. AVG()

计算窗口内值的平均值。

SELECT 
  name,
  department,
  salary,
  AVG(salary) OVER (PARTITION BY department) AS avg_salary
FROM employees;

计算每个部门员工薪水的平均值。

执行结果

namedepartmentsalaryavg_salary
AliceSales50004666.67
BobSales45004666.67
CarolSales45004666.67
DaveHR30003000

说明
计算每个部门的平均薪水,结果为浮点数以反映精确的平均值。

6. MIN()MAX()

分别找出窗口内的最小值和最大值。

SELECT 
  name,
  department,
  salary,
  MIN(salary) OVER (PARTITION BY department) AS min_salary,
  MAX(salary) OVER (PARTITION BY department) AS max_salary
FROM employees;

这个例子找出每个部门中的最低和最高薪水。

执行结果

namedepartmentsalarymin_salarymax_salary
AliceSales500045005000
BobSales450045005000
CarolSales450045005000
DaveHR300030003000

说明
每个部门的最低和最高薪水。

7. LEAD()LAG()

LEAD() 查看后面的值,LAG() 查看前面的值。

SELECT 
  name,
  department,
  salary,
  LAG(salary) OVER (PARTITION BY department ORDER BY salary) AS previous_salary,
  LEAD(salary) OVER (PARTITION BY department ORDER BY salary) AS next_salary
FROM employees;

这个例子显示了每位员工在同部门的前一位和后一位员工的薪水。

执行结果

namedepartmentsalaryprevious_salarynext_salary
AliceSales5000NULL4500
BobSales450050004500
CarolSales45004500NULL
DaveHR3000NULLNULL

说明
LAG() 显示前一行的薪水,而LEAD()显示后一行的薪水。

8. FIRST_VALUE()LAST_VALUE()

FIRST_VALUE()LAST_VALUE() 是 MySQL 中的窗口函数,它们用于从一组记录中分别获取该组内的第一个值和最后一个值,这些值是根据窗口中的特定排序规则确定的。这两个函数非常有用,特别是在需要分析数据范围内的极值时。

FIRST_VALUE()

此函数返回窗口中第一个记录的值,通常与 OVER() 子句结合使用,该子句定义了分组和排序的规则。

SQL 代码示例:

SELECT name, department, salary,
       FIRST_VALUE(name) OVER (PARTITION BY department ORDER BY salary DESC) AS highest_earner
FROM employees;

执行结果:

namedepartmentsalaryhighest_earner
JuneSales900June
JaneSales800June
JohnSales700June
JoeMarketing800Joe
JudyMarketing750Joe
JimMarketing500Joe
JeanHR720Jean
JadeHR680Jean
JoanHR650Jean
JakeHR600Jean

LAST_VALUE()

此函数返回窗口中最后一个记录的值。为了使 LAST_VALUE() 在不同的数据库管理系统中表现一致,通常需要设定窗口的 ROWS BETWEEN 子句。

SQL 代码示例:

SELECT name, department, salary,
       LAST_VALUE(name) OVER (PARTITION BY department ORDER BY salary DESC 
                              ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS lowest_earner
FROM employees;

执行结果:

namedepartmentsalarylowest_earner
JuneSales900John
JaneSales800John
JohnSales700John
JoeMarketing800Jim
JudyMarketing750Jim
JimMarketing500Jim
JeanHR720Jake
JadeHR680Jake
JoanHR650Jake
JakeHR600Jake

这两个函数在实际应用中可以帮助我们快速识别出每个部门的最高或最低薪资者,或是其他相关的业务指标最值。

OVER() 子句参数

  1. PARTITION BY - 将数据分成不同的分区(组),窗口函数会在每个分区内独立计算。
  2. ORDER BY - 在窗口内对行进行排序,影响窗口函数的计算结果。
  3. ROWS/RANGE BETWEEN - 定义窗口的范围。ROWS 指按物理行距离来计算,而 RANGE 与值的范围有关。

示例与执行结果

假设我们有一个名为 sales 的表格,包含以下列和数据:

employee_idsale_datesales_amount
12020-01-01100
12020-01-02150
22020-01-01200
22020-01-02250
示例 1:使用 SUM() 窗口函数计算累计销售额

SQL 语句:

SELECT employee_id, sale_date, sales_amount,
       SUM(sales_amount) OVER (PARTITION BY employee_id ORDER BY sale_date) AS cumulative_sales
FROM sales;

执行结果:

employee_idsale_datesales_amountcumulative_sales
12020-01-01100100
12020-01-02150250
22020-01-01200200
22020-01-02250450
示例 2:使用 ROW_NUMBER() 窗口函数进行排序

SQL 语句:

SELECT employee_id, sale_date, sales_amount,
       ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY sales_amount DESC) AS rank
FROM sales;

执行结果:

employee_idsale_datesales_amountrank
12020-01-021501
12020-01-011002
22020-01-022501
22020-01-012002

在 SQL 中使用 ROWS BETWEEN 子句可以非常精确地定义窗口函数的计算范围。这个子句通常用于指定窗口内的行的相对位置,用于计算如累积总和、移动平均等。

ROWS BETWEEN 子句参数

ROWS BETWEEN 子句可以接受几种不同的参数来定义窗口的起始点和终点:

  1. UNBOUNDED PRECEDING - 窗口开始于分区的第一行。
  2. UNBOUNDED FOLLOWING - 窗口结束于分区的最后一行。
  3. CURRENT ROW - 窗口的起点或终点是当前行。
  4. n PRECEDING - 窗口起始于当前行之前的 n 行,其中 n 是一个正整数。
  5. n FOLLOWING - 窗口结束于当前行之后的 n 行,其中 n 是一个正整数。

示例与执行结果

假设我们继续使用之前的 sales 表,现在我们来看一个计算移动平均的例子。

示例:计算每位员工的移动销售平均值

SQL 语句:

SELECT employee_id, sale_date, sales_amount,
       AVG(sales_amount) OVER (PARTITION BY employee_id ORDER BY sale_date
                               ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS moving_avg
FROM sales;

执行结果:

employee_idsale_datesales_amountmoving_avg
12020-01-01100100.0
12020-01-02150125.0
22020-01-01200200.0
22020-01-02250225.0

这个例子中,我们计算了一个移动平均值,窗口包括当前行和前一行。对于每个员工的第一行,因为没有前一行,所以移动平均值等于当前行的 sales_amount

通过这样的 SQL 语句和 ROWS BETWEEN 子句的不同参数组合,可以灵活地控制窗口函数的计算范围,实现各种复杂的数据分析任务。

更多问题咨询

Cos机器人

  • 32
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值