MySQL窗口函数全解析,你掌握了吗?

MySQL窗口函数全解析,你掌握了吗?一 引言简述 MySQL 从 8 0 版本开始支持窗口函数 它的出现为数据处理和分析带来了极大的便利 在日常开发业务中 我们常常会遇到需要在分组统计结果里针对每一条记录进行计算的情况 像聚合统计 数据挖掘等场景就经常需要这样的操作 而窗口函数

大家好,欢迎来到IT知识分享网。

一、引言

MySQL窗口函数全解析,你掌握了吗?

简述

MySQL 从 8.0 版本开始支持窗口函数,它的出现为数据处理和分析带来了极大的便利。在日常开发业务中,我们常常会遇到需要在分组统计结果里针对每一条记录进行计算的情况,像聚合统计、数据挖掘等场景就经常需要这样的操作,而窗口函数在这些场景中起着至关重要的作用。比如说,我们要统计每个部门员工的业绩排名,或者分析不同类别产品的销售情况并找出各类别中的畅销款等,使用窗口函数就能轻松搞定。

以往,我们可能需要通过较为复杂的方式,比如借助临时变量、多重嵌套查询等来实现类似功能,但窗口函数将这些操作进行了简化,让我们可以更高效地获取想要的数据结果。它可以像聚合函数一样对一组数据进行分析,但又不同于聚合函数将一组数据汇总成单个结果,窗口函数是为每一行数据都返回一个结果,从而保留了每一行数据原本的信息以及其对应的分析值。接下来,咱们就详细地了解一下 MySQL 中的窗口函数吧。

二、窗口函数基础概念

MySQL窗口函数全解析,你掌握了吗?

(一)定义及理解

在 MySQL 中,窗口函数是一种非常实用的功能。我们可以把 “窗口” 具象地理解为一个记录集合,而窗口函数就是在满足某些特定条件的记录集合上执行的特殊函数。比如说,我们可以把一个部门里所有员工的信息看作是一个窗口,然后在这个窗口内去进行相应的函数计算。

那它和普通聚合函数有什么区别呢?普通聚合函数,像 SUM(求和)、AVG(求平均)、COUNT(计数)等,操作后会将多条记录聚合为一条,例如使用 GROUP BY 对员工按部门分组后求平均工资,最终呈现的结果是每个部门只有一条平均工资的数据记录。但窗口函数不同,它是针对每一条记录都会执行相应的计算,执行完后记录的数量并不会改变,依旧保留了原始数据的每一行,并且为每一行都返回一个基于对应窗口计算出的结果。例如在统计各部门员工工资情况时,使用窗口函数可以既展示每个员工的工资,又在每行数据里展示出所在部门的工资总和、平均工资等相关统计值,方便我们进行更细致的数据分析。

(二)语法结构

窗口函数的语法形式一般为:<窗口函数> OVER ([PARTITION BY 字段名 ORDER BY 字段名 ASC|DESC]) ,下面详细介绍一下各部分的作用和使用方式。

首先是 “OVER” 关键字,它用于指定函数执行的窗口范围。如果 “OVER” 后面括号中的内容为空,那就意味着窗口包含满足 WHERE 条件的所有记录,窗口函数会基于所有满足 WHERE 条件的记录进行计算。

“PARTITION BY” 子句,其作用是将数据行拆分成多个分区(组),这一点和 “GROUP BY” 分组有些类似。例如在员工信息表中,我们可以按照部门字段 “department” 通过 “PARTITION BY department” 来进行分区,这样就能针对每个部门分别执行后续的窗口函数操作了。

“ORDER BY” 子句,它在 “OVER” 子句里的作用是指定分区内的排序方式,与普通查询语句里的 “ORDER BY” 子句功能类似。比如我们可以根据员工的工资字段 “salary” 通过 “ORDER BY salary DESC” 来按照工资降序排列,这会影响窗口函数在计算时对分区内数据的处理顺序,像排名类的窗口函数就会根据这个排序来确定每条记录的序号或者排名情况等。

还有 “FRAME” 子句(在有些语法示例里会出现),它用于在当前分区内指定一个计算窗口,也就是定义一个与当前行相关的数据子集。例如可以设定为 “rows between unbounded preceding and current row”,意思就是范围为从之前所有的行到当前行;还可以像 “rows between 2 preceding and current row” 这样,表示从前面 2 行到当前行的范围等,通过它可以灵活地控制窗口函数计算所涉及的数据范围,常被用来作为滑动窗口使用。

例如,我们有一个名为 “employees” 的员工信息表,包含 “employee_id”(员工编号)、“department_id”(部门编号)、“salary”(工资)等字段,想要查看每个部门内员工按照工资降序排列后的序号、排名以及所在部门的工资总和,可以这样写查询语句:

SELECT employee_id, department_id, salary, ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS row_num, RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank_num, SUM(salary) OVER (PARTITION BY department_id ORDER BY salary DESC) AS sum_salary FROM employees;

在上述语句中,“ROW_NUMBER ()”“RANK ()” 以及 “SUM ()” 在这里都是窗口函数,通过 “PARTITION BY department_id” 按照部门进行分区,再依据 “ORDER BY salary DESC” 按工资降序在分区内排序,进而得出我们想要的不同分析结果展示在每一行数据里。

三、窗口函数的分类及示例

MySQL窗口函数全解析,你掌握了吗?

(一)序号函数

1. ROW_NUMBER()

ROW_NUMBER () 函数能够对数据中的序号进行顺序显示。例如,我们创建一个名为 “students” 的学生成绩表,包含 “student_id”(学生编号)、“subject”(科目)、“score”(成绩)等字段。现在想要查看每个科目内学生按照成绩降序排列后的序号,可以使用以下查询语句:

SELECT student_id, subject, score, ROW_NUMBER() OVER (PARTITION BY subject ORDER BY score DESC) AS row_num FROM students;

在上述语句中,通过 “PARTITION BY subject” 按照科目进行分区,再依据 “ORDER BY score DESC” 按成绩降序在分区内排序,ROW_NUMBER () 函数就会为每个分区内的每一行数据从 1 开始依次分配序号,即使存在相同成绩的情况,也会按照顺序依次赋予不同的序号,比如同一科目下成绩相同的两名学生,序号会是连续的不同数字,像第一名是 1,并列第一名的另一位则是 2,第三名就会是 3 等等。

2. RANK()

RANK () 函数的作用主要是对序号进行并列排序,并且会跳过重复的序号。同样以 “students” 表为例,使用以下查询语句查看每个科目内学生按成绩降序排列后的排名情况:

SELECT student_id, subject, score, RANK() OVER (PARTITION BY subject ORDER BY score DESC) AS rank_num FROM students;

假设在某个科目中有两名学生成绩并列第一,那么使用 RANK () 函数,这两名学生的排名都会显示为 1,而接下来的学生排名就会跳过 2,直接显示为 3 了,因为前面已经有两个第一名了,这体现出它在处理相同数值数据时,排名序号会出现间断的特点,与 ROW_NUMBER () 函数在相同场景下序号连续的情况是不同的。

3. DENSE_RANK()

DENSE_RANK () 函数对序号进行并列排序,但不会跳过重复的序号。还是基于 “students” 表,查询语句如下:

SELECT student_id, subject, score, DENSE_RANK() OVER (PARTITION BY subject ORDER BY score DESC) AS dense_rank_num FROM students;

比如在某科目下有两名学生成绩相同并列第一,使用 DENSE_RANK () 函数时,这两名学生排名都是 1,紧接着下一名学生的排名会正常显示为 2,序号是连续排列的,并不会像 RANK () 函数那样跳过重复序号后的数字,通过这样的对比,可以更清晰地看出它与 RANK () 函数在处理相同数值时序号呈现情况的差异。

(二)开窗聚合函数

开窗聚合函数(如 SUM,AVG,MIN,MAX 等)有着独特的特点,它可以在行记录上计算某个字段的结果时,将窗口范围内的数据输入到聚合函数中,而且并不改变行数。

例如,我们有一个 “employees” 的员工信息表,包含 “employee_id”(员工编号)、“department”(部门)、“salary”(薪资)等字段,现在有一个需求是对每个部门的员工按照薪资排序,然后新增一列展示每位员工前面一位同事的薪资总和,代码可以这样写:

SELECT employee_id, department, salary, SUM(salary) OVER (PARTITION BY department ORDER BY salary ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS sum_previous_salary FROM employees;

在这个示例中,通过 “PARTITION BY department” 按照部门分区,“ORDER BY salary” 按薪资排序,再利用开窗聚合函数 SUM 结合窗口范围定义 “ROWS BETWEEN 1 PRECEDING AND CURRENT ROW”,实现了在不改变原有行数的基础上,为每一行数据计算出对应的前面一位同事薪资总和这一结果,方便我们进行更多维度的数据查看与分析。

(三)分布函数

1. CUME_DIST()

CUME_DIST () 函数用于查询小于或等于某个值的比例。其计算原理是用窗口内小于等于当前行 rank 值的行数除以窗口内总行数。

例如,我们有一个 “products” 产品表,包含 “product_id”(产品编号)、“category”(类别)、“price”(价格)等字段,现在想要查看每个类别产品价格的分布比例情况,查询语句可以这样写:

SELECT product_id, category, price, CUME_DIST() OVER (PARTITION BY category ORDER BY price) AS cume_dist_value FROM products;

在上述代码中,通过 “PARTITION BY category” 按照产品类别进行分区,再依据 “ORDER BY price” 按价格排序,CUME_DIST () 函数就会为每一行数据计算出在当前类别中,小于或等于该行产品价格的比例数值,从而帮助我们了解不同类别产品价格在各自类别内的分布占比情况。

2. PERCENT_RANK()

PERCENT_RANK () 函数是等级值百分比函数,计算公式为 (rank – 1) / (rows – 1),其中 rank 为 RANK () 函数产生的序号,rows 为当前窗口的记录总行数。

假设我们有一个 “students_scores” 学生成绩表,包含 “student_name”(学生姓名)、“class”(班级)、“score”(成绩)等字段,想要查看每个班级内学生成绩的百分比排名情况,代码如下:

SELECT student_name, class, score, PERCENT_RANK() OVER (PARTITION BY class ORDER BY score DESC) AS percent_rank_value FROM students_scores;

在这个示例里,通过 “PARTITION BY class” 按班级分区,“ORDER BY score DESC” 按成绩降序排列,PERCENT_RANK () 函数会依据上述计算公式,为每个班级内的每一位学生计算出对应的成绩百分比排名,让我们能从另一个角度去分析学生成绩在班级内的相对位置情况。

(四)前后函数

1. LAG()

LAG () 函数的功能是返回位于当前行的前 n 行的 expr 的值。比如说,在一个 “students_scores” 学生成绩表中,包含 “student_id”(学生编号)、“exam_date”(考试日期)、“score”(成绩)等字段,现在有一个需求是查询每位学生前 1 名同学的成绩和当前同学成绩的差值,代码可以这样写:

SELECT student_id, exam_date, score, score - LAG(score, 1) OVER (ORDER BY exam_date) AS score_difference FROM students_scores;

在上述代码中,通过 “ORDER BY exam_date” 按照考试日期排序,然后使用 LAG (score, 1) 表示获取当前行前 1 行的成绩值,再用当前行的成绩减去前一行的成绩,就得到了成绩差值,这样就能清晰地看到每位学生与前一位同学成绩的变化情况了,便于分析成绩波动趋势等。

2. LEAD()

LEAD () 函数能返回位于当前行的后 n 行的 expr 的值。例如,在一个 “sales_records” 销售记录表中,包含 “salesperson_id”(销售人员编号)、“sales_date”(销售日期)、“sales_amount”(销售金额)等字段,现在想要查看每位销售人员下一次销售的金额情况,代码示例如下:

SELECT salesperson_id, sales_date, sales_amount, LEAD(sales_amount, 1) OVER (PARTITION BY salesperson_id ORDER BY sales_date) AS next_sales_amount FROM sales_records;

这里通过 “PARTITION BY salesperson_id” 按照销售人员编号分区,“ORDER BY sales_date” 按销售日期排序,使用 LEAD (sales_amount, 1) 就能获取到当前行对应的该销售人员下一次销售的金额数值,这对于分析销售人员业绩的连续性、波动情况等有着重要的作用。

(五)头尾函数

1. FIRST_VALUE()

FIRST_VALUE () 函数可返回第一个 expr 的值。比如在一个 “employees_hired” 员工入职信息表中,包含 “employee_name”(员工姓名)、“hire_date”(入职日期)、“salary”(薪资)等字段,现在有一个需求是截止到当前,按照入职日期排序查询第 1 个入职员工的薪资情况,代码如下:

SELECT employee_name, hire_date, salary, FIRST_VALUE(salary) OVER (ORDER BY hire_date) AS first_employee_salary FROM employees_hired;

在上述代码中,通过 “ORDER BY hire_date” 按照入职日期排序,FIRST_VALUE (salary) 就会返回按照这个排序下第一个员工的薪资数值,方便我们了解最早入职员工的薪资水平,也可以作为一个参考基准,与后续入职员工的薪资进行对比分析等。

2. LAST_VALUE()

LAST_VALUE () 函数能够返回最后一个 expr 的值。例如,在一个 “orders” 订单表中,包含 “order_id”(订单编号)、“order_date”(订单日期)、“total_amount”(订单总金额)等字段,现在想要查询截止到当前按照订单日期排序的最后一个订单的总金额情况,代码可以这样写:

SELECT order_id, order_date, total_amount, LAST_VALUE(total_amount) OVER (ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_order_amount FROM orders;

这里通过 “ORDER BY order_date” 按订单日期排序,并使用 “ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING” 定义窗口范围为从最开始到最后一行,这样 LAST_VALUE (total_amount) 就能准确返回按照此排序下最后一个订单的总金额了,有助于我们查看最新订单的金额情况等分析需求。

(六)其他函数

1. NTH_VALUE(expr, n)

NTH_VALUE (expr, n) 函数的作用是返回相对于窗口的第一行的窗口框架的指定行的表达式值。例如,我们有一个 “employees_salary” 员工薪资表,包含 “employee_id”(员工编号)、“department”(部门)、“salary”(薪资)等字段,现在想要显示每个员工的薪资中排名第 2 或者第 3 的薪资情况,代码示例如下:

SELECT employee_id, department, salary, NTH_VALUE(salary, 2) OVER (PARTITION BY department ORDER BY salary DESC) AS second_highest_salary, NTH_VALUE(salary, 3) OVER (PARTITION BY department ORDER BY salary DESC) AS third_highest_salary FROM employees_salary;

在上述代码中,通过 “PARTITION BY department” 按照部门分区,“ORDER BY salary DESC” 按薪资降序排列,然后使用 NTH_VALUE (salary, 2) 和 NTH_VALUE (salary, 3) 分别获取每个部门内薪资排名第 2 和第 3 的数值,这对于分析部门内薪资结构、不同层次薪资水平等方面很有帮助。

2. NTILE(n)

NTILE (n) 函数可将分区中的有序数据分为 n 个等级,记录等级数。比如,我们有一个 “employees” 员工信息表,包含 “employee_id”(员工编号)、“department”(部门)、“hire_date”(入职日期)等字段,现在要将每个部门员工按照入职日期分成 3 组,代码如下:

SELECT employee_id, department, hire_date, NTILE(3) OVER (PARTITION BY department ORDER BY hire_date) AS group_number FROM employees;

在这个示例里,通过 “PARTITION BY department” 按照部门分区,“ORDER BY hire_date” 按入职日期排序,再使用 NTILE (3) 函数,就会为每个部门内的员工按照入职先后顺序均匀地划分成 3 个等级组,通过查看 “group_number” 列就能知道每位员工所在的分组情况,有助于进一步分析不同入职阶段员工的分布等情况。

四、窗口函数的应用场景举例

MySQL窗口函数全解析,你掌握了吗?

(一)数据准备

在举例说明窗口函数的应用场景前,咱们需要先创建相关的数据表,并插入一些模拟数据,方便后续进行操作演示。

假设我们创建一个名为 “users” 的用户表,包含 “user_id”(用户编号,主键)、“user_name”(用户名)、“gender”(性别)等字段,创建语句及插入示例数据如下:

CREATE TABLE users ( user_id INT PRIMARY KEY, user_name VARCHAR(50), gender VARCHAR(10) ); INSERT INTO users (user_id, user_name, gender) VALUES (1, '张三', '男'), (2, '李四', '女'), (3, '王五', '男'), (4, '赵六', '女');

再创建一个名为 “transactions” 的交易表,包含 “transaction_id”(交易编号,主键)、“user_id”(关联用户编号)、“transaction_amount”(交易金额)、“transaction_date”(交易日期)等字段,创建语句及插入示例数据如下:

CREATE TABLE transactions ( transaction_id INT PRIMARY KEY, user_id INT, transaction_amount DECIMAL(10, 2), transaction_date DATE ); INSERT INTO transactions (transaction_id, user_id, transaction_amount, transaction_date) VALUES (1, 1, 100.00, '2023-01-01'), (2, 1, 200.00, '2023-01-05'), (3, 2, 150.00, '2023-01-02'), (4, 2, 80.00, '2023-01-06'), (5, 3, 300.00, '2023-01-03'), (6, 3, 120.00, '2023-01-07'), (7, 4, 90.00, '2023-01-04'), (8, 4, 250.00, '2023-01-08');

有了这两张表的数据,我们就可以开始演示窗口函数在不同场景下的应用啦。

(二)计算用户交易占比

在拥有上述的用户表 “users” 和交易表 “transactions” 的前提下,现在来看看如何通过窗口函数计算出每个用户的交易量占总交易量的百分比。

首先,我们需要通过子查询先对每个用户的交易金额进行汇总,然后再利用窗口函数结合聚合函数来计算占比。具体的代码实现如下:

SELECT u.user_name, t.total_amount, SUM(t.total_amount) OVER () AS total_all_amount, t.total_amount / SUM(t.total_amount) OVER () AS percentage FROM ( SELECT user_id, SUM(transaction_amount) AS total_amount FROM transactions GROUP BY user_id ) t JOIN users u ON t.user_id = u.user_id;

在这段代码中:

  • 最内层的子查询 (SELECT user_id, SUM(transaction_amount) AS total_amount FROM transactions GROUP BY user_id) 是按照用户编号对交易表 “transactions” 进行分组,并计算出每个用户的总交易金额,将其命名为 “total_amount”。
  • 接着通过 JOIN 操作将这个子查询的结果与用户表 “users” 进行关联,以便能显示出对应的用户名。
  • SUM(t.total_amount) OVER () 这部分就是窗口函数的应用了,这里的 OVER() 括号内为空,表示窗口包含满足前面查询条件的所有记录,也就是对所有用户的总交易金额进行求和,得到总的交易量(命名为 “total_all_amount”)。
  • 最后,用每个用户的总交易金额 t.total_amount 除以总的交易量 SUM(t.total_amount) OVER () ,就得到了每个用户交易量占总交易量的百分比 “percentage”。

这样,我们就能清晰地看到每个用户的交易在整体中所占的比重了。

(三)查找每日交易金额最高用户

利用窗口函数在给定的用户表和交易表数据基础上,来计算出每天交易金额位于第一的用户。具体的实现思路和代码操作如下:

SELECT sub.name, sub.transaction_date, sub.transaction_amount FROM ( SELECT u.user_name AS name, t.transaction_date, t.transaction_amount, ROW_NUMBER() OVER (PARTITION BY t.transaction_date ORDER BY t.transaction_amount DESC) AS ranking FROM transactions t JOIN users u ON t.user_id = u.user_id ) sub WHERE sub.ranking = 1;

在这个代码示例里:

  • 首先在子查询中,通过 JOIN 操作将 “transactions” 表和 “users” 表关联起来,这样就能获取到交易对应的用户名等信息了。
  • 接着使用窗口函数 ROW_NUMBER() OVER (PARTITION BY t.transaction_date ORDER BY t.transaction_amount DESC) ,这里的 PARTITION BY t.transaction_date 是按照交易日期进行分区,意味着会对每一天的数据分别进行处理;ORDER BY t.transaction_amount DESC 则是在每个分区(也就是每天的数据里)按照交易金额进行降序排序;ROW_NUMBER() 函数会为分区内的每一行数据按照排序结果依次分配序号(这里命名为 “ranking”),序号从 1 开始,交易金额最高的那行就会被分配序号 1。
  • 最后,在最外层的查询中通过 WHERE sub.ranking = 1 这个条件,筛选出序号为 1 的数据,也就是每天交易金额最高的用户对应的那行数据,包含用户名、交易日期以及交易金额等信息了。

通过这样的步骤,我们就能准确地找出每天交易金额最高的用户了。

(四)其他常见应用场景拓展

除了上面提到的应用场景外,窗口函数还有很多其他常见的用法,下面简单罗列一些并说明大致思路和对应的窗口函数运用方向,方便大家进一步探索更多用法:

  • 查询组内第 N 项记录

比如我们有一个商品销售数据表,包含 “product_id”(商品编号)、“product_type”(商品类型)、“sales_volume”(销售量)等字段,现在想要查询每种商品类型下销售量排名第 2 的商品信息。大致思路是先按照商品类型进行分区,然后在每个分区内按照销售量降序排序,再使用 ROW_NUMBER() 函数为每行数据分配序号,最后筛选出序号为 2 的记录即可。代码示例如下:

SELECT sub.product_id, sub.product_type FROM ( SELECT product_id, product_type, ROW_NUMBER() OVER (PARTITION BY product_type ORDER BY sales_volume DESC) AS ranking FROM products ) sub WHERE sub.ranking = 2;
  • 查询不同种类下数量前 N 的记录

假设我们有一个课程选课数据表,包含 “course_id”(课程编号)、“grade”(年级)、“student_number”(选课学生数量)等字段,要查询每个年级里最受欢迎的(也就是选课学生数量最多的)两门课程。实现思路是先通过子查询按照年级和课程进行分组统计出每门课程的选课学生数量,然后在外层查询中按照年级分区,根据选课学生数量降序排序,使用 ROW_NUMBER() 函数分配序号,最后筛选出序号小于等于 2 的记录。示例代码如下:

SELECT sub.grade, sub.course_id FROM ( SELECT grade, course_id, ROW_NUMBER() OVER (PARTITION BY grade ORDER BY student_number DESC) AS ranking FROM ( SELECT grade, course_id, COUNT(*) AS student_number FROM courses GROUP BY grade, course_id ) sub_query ) sub WHERE sub.ranking <= 2;
  • 查询前 20% 的记录

例如有一个用户消费数据表,包含 “user_name”(用户名)、“consumption_amount”(消费金额)等字段,想找出消费金额在前 20% 的用户。可以利用 NTILE() 函数,先按照用户的消费总额度进行排序,然后使用 NTILE(5) 将所有用户分为 5 组(因为 20% 就是五分之一嘛),这样排名第一组的就是前 20% 的用户了。代码如下:

SELECT sub.user_name FROM ( SELECT user_name, NTILE(5) OVER (ORDER BY SUM(consumption_amount) DESC) AS ranking FROM user_consumption GROUP BY user_name ) sub WHERE sub.ranking = 1;
  • 查询连续登录天数为特定天数的记录

假设有一个用户登录记录表,包含 “user_name”(用户名)、“login_date”(登录日期)等字段,要查询连续登录天数为 7 天的用户。大致思路是先利用 LEAD() 函数查询每个用户后 7 条记录对应的日期(如果没有则返回 NULL),然后判断用户登录日期往后推 7 天的日期是否与 LEAD() 函数得到的日期相等,相等则说明是连续登录了 7 天的用户。代码示例如下:

SELECT sub.user_name FROM ( SELECT user_name, login_date, LEAD(login_date, 7) OVER (PARTITION BY user_name ORDER BY login_date) AS next_date FROM user_login ) sub WHERE sub.next_date IS NOT NULL AND DATE_ADD(sub.login_date, INTERVAL 7 DAY) = CAST(sub.next_date AS DATE);

这些只是窗口函数众多应用场景中的一部分,大家可以根据实际业务需求,灵活运用窗口函数来解决各种数据分析和查询的问题哦,多多尝试,说不定会发现更多好用的方法呢。

五、总结

MySQL窗口函数全解析,你掌握了吗?

通过以上对 MySQL 窗口函数的详细介绍,我们可以看到它在数据处理和分析领域的重要性不容小觑。

从功能特性来看,它既有着类似聚合函数对一组数据进行分析的能力,又能为每一行数据都返回一个结果,避免了像普通聚合函数那样将多条记录聚合为一条而丢失每行原始信息的情况,这使得我们在面对诸如排名、占比计算、前后行数据对比等复杂需求时,可以更加灵活高效地获取想要的数据。

在分类方面,序号函数里的 ROW_NUMBER ()、RANK ()、DENSE_RANK () 各自有着独特的序号分配逻辑,能满足不同场景下对数据排序和排名的要求;开窗聚合函数可以在不改变行数的基础上,实现如计算累计值、移动平均值等操作;分布函数 CUME_DIST ()、PERCENT_RANK () 则帮助我们了解数据在分组内的分布占比以及相对排名百分比情况;前后函数 LAG ()、LEAD () 方便获取当前行前后特定行的数据,利于分析数据的变化趋势;头尾函数 FIRST_VALUE ()、LAST_VALUE () 可以快速定位到窗口内的首尾值;还有像 NTH_VALUE (expr, n)、NTILE (n) 等其他函数,也在分析特定位置的值以及对数据进行分组划分等级等方面发挥着重要作用。

在应用场景上,无论是计算用户交易占比、查找每日交易金额最高用户,还是诸如查询组内第 N 项记录、不同种类下数量前 N 的记录、前 20% 的记录、连续登录天数为特定天数的记录等拓展场景,窗口函数都展现出了强大的实用性,能极大地简化我们的 SQL 编写,提升数据分析效率。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/166778.html

(0)
上一篇 2025-01-09 14:26
下一篇 2025-01-09 14:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信