窗口函数大揭秘!轻松计算数据累计占比,玩转数据分析的绝佳利器

窗口,函数,揭秘,轻松,计算,数据,累计,玩转,数据分析,绝佳,利器 · 浏览次数 : 331

小编点评

**窗口函数在累计分析场景中的应用** **简介** 窗口函数是数据库中一种强大的函数,可以用来在每行上打开一个指定大小的计算窗口,并在此窗口中进行分析。在累计分析场景中,窗口函数可以用来计算每个分类每月的每日累计损耗量、当月每日余量和每月累计消耗占比。 **SQL中的窗口函数** `SUM(cost) over(partition by cate,MONTH(record_date) order by record_date)` 这段 SQL 语句计算每个分类每月的每日累计损耗总额。`partition by cate` 表示对数据分组,`MONTH(record_date)` 表示按月份分组,`order by record_date` 表示按时间降序排序。 **优化** 为了优化查询结果,可以考虑以下方法: * 使用索引优化查询条件。 * 使用缓存优化结果。 * 使用并行执行多个窗口函数。 **示例** 假设我们有以下数据: | 分类 | 日期 | 耗材耗损 | |---|---|---| | 产品 A | 2023-06-01 | 100 | | 产品 A | 2023-06-02 | 120 | | 产品 B | 2023-06-03 | 80 | | 产品 B | 2023-06-04 | 100 | | 产品 C | 2023-06-05 | 150 | 使用 SQL 的 `SUM(cost) over(partition by cate,MONTH(record_date) order by record_date)` 语句,可以计算每个分类每月的每日累计损耗总额: ```sql select cate, record_date, init_value, sum(cost) over(partition by cate, MONTH(record_date) order by record_date) as cm_costfrom material_data md ``` **结论** 窗口函数是在累计分析场景中非常有用的工具。通过在每行上打开一个计算窗口,窗口函数可以提供更细粒度的分析结果。

正文

上一篇文章《如何用窗口函数实现排名计算》中小编为大家介绍了窗口函数在排名计算场景中的应用,但实际上窗口函数除了可以进行单行计算,还可以在每行上打开一个指定大小的计算窗口,这个计算窗口可以由SQL中的语句具体指定,大到整个分区作用域,小到当前行指定的某个偏移行(比如 当前行的上一行、下一行,整个计算窗口被称作 frame)。今天小编就为大家介绍窗口函数在累计分析场景中的应用。

需要注意的是,如果您的数据库版本低于以下版本,将无法使用文章中使用到的窗口函数。

1.Mysql (>=8.0)

2. PostgreSQL(>=11)
3. SQL Server(>=2012)
4. Oracle(>=8i)
5. SQLite(>=3.28.0)

需求背景

和上一篇文章一样,为了让大家更好的理解,我将以工厂的耗材损耗数据作为查询条件背景:假设现在有某个工厂刚刚完成了一次耗材的加工,在加工的过程中记录了耗材分类,每日的记录时间、每日的耗材耗损数和当月的月初耗材供给量,如下表所示:

现在这家公司的老板想看一下:

1. 各个耗材的每日累计损耗量。

2. 各个耗材的当月每日余量。

3. 各个耗材的每月累计消耗占比。

查询各个耗材的每日累计损耗量

执行如下的SQL语句。

select cate,record_date,init_value,SUM(cost) over(partition by cate,MONTH(record_date) order by record_date ) as cm_cost

from material_data md;

可以看到,通过上述 SQL 查询就已经得到了每个分类每月的每日累计耗损量。这里为大家解释下SQL中的重点部分:

SUM(cost) over(partition by cate,MONTH(record_date) order by record_date );

在上一篇文章中我们介绍过,partition by 指定了计算分区, order by 决定了计算的行顺序, 那累计效果又是谁来完成的呢, 这里小编把刚刚的 SQL 稍微改造一下就会更清晰。

select cate,record_date,init_value,SUM(cost) over(partition by cate,MONTH(record_date) order by record_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) as cm_cost

from material_data md;

改造后的SQL和最开始的查询SQL达成的效果是一致的, 我们可以看到改造SQL在 order by 后加了一段代码:

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

小编为大家拆解一下这个代码,第一个 ROWS 表示接下来的 Frame 窗口指定为行模式, BETWEEN 关键字表示接下来的语句效果是指定 窗口范围, UNBOUNDED 和PRECEDING 是两个关键字的组合,前者表示 该计算窗口在 ↑ 方向的边界为最顶部,对应到 partion by 分区中 6 月份的计算域,UNBOUNDED PRECEDING 表示6月份每一行的窗口上界为 order by record_date 顺序下的最小值,即 2023/06/01号的记录, 同样的 接下来的 AND CURRENT ROW 则指定了计算frame 窗口的 ↓ 边界为当前行。 最后我们重新梳理下这个计算窗口, 在每月每个分类的计算分区下,每一行的计算窗口为 从本月的最小日期 到当前行的所有记录,,联系到最开始 SUM(cost) 聚合就能够理解 为什么这条 SQL 能计算出对应的累计值了。

这里可以扩展说明一下,确定计算窗口大小的关键字 除了UNBOUNDED PRECEDING和CURRENT ROW 之外还有 UNBOUNDED FOLLOWING, 如果 UNBOUNDED PRECEDING 表示上边界的顶部, 那 UNBOUNDED FOLLOWING 就表示下边界的底部。所以如果指定计算窗口为 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING, 则表示在整个分区计算域中进行聚合运算。另外, UNBOUNDED 其实是非必须的, 这里可以替换为任意数字表示 针对当前行的偏移行数。比如 1 PRECEDING 表示 当前行的上一行, 1 FOLLOWING 表示当前行的下一行, 我们通过指定计算窗口为 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING 就能计算 每一行从上一行到下一行之间这三行的累计值。至于说 CURRENT ROW 则指定为当前行,这也是为什么能做累计求和的关键。
类似的,MAX()、AVG() 等聚合函数也适用于以上的规则, 我们可以在每一行的指定窗口内来计算最大值,平均值等聚合值。

查询各个耗材的当月每日余量

查询Sql:

select

cate,

record_date,

init_value,

init_value - SUM(cost) over(partition by cate,MONTH(record_date) order by record_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) as material_num

from material_data md;

也可以简写为

select

cate,

record_date,

init_value,

init_value - SUM(cost) over(partition by cate,MONTH(record_date) order by record_date ) as material_num

from material_data md;

查询各个耗材的每月累计消耗占比

select

md.cate,

record_date,

init_value,

cost/ sum(cost) over(partition by cate,MONTH(record_date) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as cm_cost

from material_data md

同理,可以简写为:

select

md.cate,

record_date,

init_value,

cost/ sum(cost) over(partition by cate,MONTH(record_date)) as cm_cost

from material_data md

接着就可以根据每天的消耗量占比,来挖掘实际业务场景, 对异常消耗量数据进行对应跟踪。


总结

累计运算也是窗口函数在业务场景中使用得最频繁得一个场景,尤其是销售业务累计排名,业务器材每日消耗程度, 每日余量警报等场景都会用到, 希望能对各位有所帮助。而关于 frame计算窗口得灵活调整还有更多丰富特性,后续(第三篇)还会为大家介绍偏移计算场景。

扩展链接:

如何快速实现多人协同编辑?

Excel中自定义手写签名

高级SQL分析函数-窗口函数(1)- 排名计算

与窗口函数大揭秘!轻松计算数据累计占比,玩转数据分析的绝佳利器相似的内容:

窗口函数大揭秘!轻松计算数据累计占比,玩转数据分析的绝佳利器

上一篇文章[《如何用窗口函数实现排名计算》](https://www.cnblogs.com/powertoolsteam/p/17627928.html)中小编为大家介绍了窗口函数在排名计算场景中的应用,但实际上窗口函数除了可以进行单行计算,还可以在每行上打开一个指定大小的计算窗口,这个计算窗口可

窗口函数实战指南:轻松掌握排名计算技巧,提升数据处理效率

> 摘要:本文由葡萄城技术团队于博客园原创并首发。转载请注明出处:[葡萄城官网](https://www.grapecity.com.cn/),葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 # 前言 SQL语句中,聚合函数在统计业务数据结果时起到了重要作用,比如计算每个业务地区的业

SQL窗口分析函数使用详解系列三之偏移量类窗口函数

1.综述 本文以HiveSQL语法进行代码演示。 对于其他数据库来说同样也适用,比如SparkSQL,FlinkSQL以及Mysql8,Oracle,SqlServer等传统的关系型数据库。 已更新第一类聚合函数类,点击这里阅读 ①SQL窗口函数系列一之聚合函数类 ②SQL窗口函数系列二之分组排序窗

row_number函数的不稳定性

row_number窗口函数的排序是不稳定排序,行的物理顺序可能会发生变化,通过巧妙的构思实现排序的稳定。

如何利用窗口函数实现精确排名计算?

前言 SQL语句中,聚合函数在统计业务数据结果时起到了重要作用,比如计算每个业务地区的业务总数、每个班级的学生平均分以及每个分类的最大值等。然而,今天小编将为大家介绍窗口函数,与聚合函数相比,它们也是一组函数,但在使用方法和适用场景上有所不同。在本章节中,我将重点介绍窗口函数中的RANK和DENSE

SQL KEEP 窗口函数等价改写案例

一哥们出条sql题给我玩,将下面sql改成不使用keep分析函数的写法。 select deptno, ename, sal, hiredate, min(sal) keep(dense_rank first order by hiredate) over(partition by deptno)

MySQL8新特性窗口函数详解

本文博主给大家详细讲解一波 MySQL8 的新特性:**窗口函数**,相信大伙看完一定能有所收获🤓。 - 本文提供的 sql 示例都是基于 MySQL8,由博主亲自执行确保可用 - 博主github地址:http://github.com/wayn111 ,欢迎大家关注,点个star # 简介 M

语音信号处理中的“窗函数”

文章代码仓库:https://github.com/LXP-Never/window_fun 窗函数贯穿整个语音信号处理,语音信号是一个非平稳的时变信号,但“**短时间内可以认为语音信号是平稳时不变的,一般 10~30ms**。 对连续的语音分帧做STFT处理,等价于截取一段时间信号,对其进行周期性

在DevExpress的GridView的列中,动态创建列的时候,绑定不同的编辑处理控件

在使用DevExpress的GridView的时候,我们为了方便,往往使用一些扩展函数,动态创建GridView列的编辑控件对象,然后我们可以灵活的对内容进行编辑或者使用一些弹出的对话框窗体进行处理内容的录入,本篇随笔就是介绍这一主题:在DevExpress的GridView的列中,动态创建列的时候,绑定不同的编辑处理控件。

窗口到底有多滑动?揭秘TCP/IP滑动窗口的工作原理

本文将深入揭示TCP/IP滑动窗口的工作原理,探讨其在确保数据准确性和实现高效通信方面的重要性。