首页 > 数据库 >SQL 实战:窗口函数进阶 – 实现复杂滑动窗口与动态累计计算

SQL 实战:窗口函数进阶 – 实现复杂滑动窗口与动态累计计算

时间:2024-12-30 19:26:25浏览次数:3  
标签:窗口 进阶 OVER id amount user SQL ORDER

窗口函数是 SQL 中非常强大的工具,能够在不改变原始数据粒度的情况下,动态进行排名、累计、滑动平均以及环比同比计算。
在实际业务场景中,窗口函数常用于构建复杂的时间序列分析,如滚动累计、移动平均、同比/环比增长等。

本文将深入探讨窗口函数的高级用法,通过具体案例展示如何利用 LAG()LEAD()NTILE()CUME_DIST() 解决滑动窗口和动态累计计算问题。


一、窗口函数回顾与高级函数简介

1. 窗口函数核心概念
  • 窗口函数 是一种在结果集中按分区按顺序对数据进行计算的函数,返回的结果与原始表数据具有相同的行数。
  • 与聚合函数不同,窗口函数不折叠行,而是在每一行上执行计算。

2. 常用窗口函数及其功能
函数说明示例
ROW_NUMBER()为每个分区内的行分配唯一编号,从 1 开始递增ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date)
RANK()类似于 ROW_NUMBER(),但排名相同则跳过名次RANK() OVER (ORDER BY score DESC)
DENSE_RANK()连续排名,不跳过DENSE_RANK() OVER (ORDER BY amount DESC)
LAG()获取当前行前 N 行的值LAG(amount, 1) OVER (PARTITION BY user_id ORDER BY date)
LEAD()获取当前行后 N 行的值LEAD(amount, 1) OVER (ORDER BY date)
NTILE(n)将分区数据分为 nNTILE(4) OVER (ORDER BY score)
CUME_DIST()累积分布,计算小于等于当前行的比例CUME_DIST() OVER (PARTITION BY category ORDER BY price)

二、实战案例:滑动窗口与动态累计计算


案例 1:计算滚动 3 个月的销售额总和

需求描述
在电商系统中,按月份统计用户的订单销售额,并计算滚动 3 个月的累计销售额


表结构 sales
sale_iduser_idsale_dateamount
11012024-01-01500
21012024-02-01600
31012024-03-01700
41012024-04-01800
51012024-05-01400
61022024-01-01300
71022024-03-01500
81022024-04-01600

SQL 实现
SELECT user_id,  
       sale_date,  
       amount,  
       SUM(amount) OVER (
           PARTITION BY user_id  
           ORDER BY sale_date  
           ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
       ) AS rolling_3m_sum  
FROM sales;

查询结果
user_idsale_dateamountrolling_3m_sum
1012024-01-01500500
1012024-02-016001100
1012024-03-017001800
1012024-04-018002100
1012024-05-014001900
1022024-01-01300300
1022024-03-01500800
1022024-04-016001400

解释

  • ROWS BETWEEN 2 PRECEDING AND CURRENT ROW 定义了一个滚动窗口,包含当前行及前两行的数据。
  • SUM(amount) 在该窗口内累计销售额,形成滚动 3 个月销售额总和


案例 2:计算同比增长率

需求描述
统计每个用户按月份的销售额,并计算与上个月相比的销售增长率(环比)同比增长率(去年同月)


SQL 实现
SELECT user_id,  
       sale_date,  
       amount,  
       LAG(amount, 1) OVER (
           PARTITION BY user_id  
           ORDER BY sale_date
       ) AS prev_month_amount,  
       ROUND((amount - LAG(amount, 1) OVER (
           PARTITION BY user_id ORDER BY sale_date
       )) / LAG(amount, 1) OVER (
           PARTITION BY user_id ORDER BY sale_date
       ) * 100, 2) AS month_growth_rate  
FROM sales;

查询结果
user_idsale_dateamountprev_month_amountmonth_growth_rate
1012024-01-01500NULLNULL
1012024-02-0160050020.00%
1012024-03-0170060016.67%
1012024-04-0180070014.29%
1012024-05-01400800-50.00%

解释

  • LAG() 函数获取前一行的销售额,用于计算环比增长率。
  • ROUND() 保留两位小数,NULL 表示首月无前一月数据。


案例 3:按销售额分位排名(四分位数)

需求描述
将用户的销售额按四分位数进行排名(将用户数据分为 4 组,每组约占 25%)。


SQL 实现
SELECT user_id,  
       amount,  
       NTILE(4) OVER (
           ORDER BY amount DESC
       ) AS quartile  
FROM sales;

查询结果
user_idamountquartile
1018001
1017001
1016002
1015002
1025003
1024003

解释

  • NTILE(4) 将数据平均分为 4 份,金额最高的前 25% 用户归为第 1 组,依次类推。

总结

  • 滑动窗口滚动累计常用于时间序列分析,如销售额、活跃用户等。
  • 使用 LAG()LEAD() 可以轻松实现环比和同比计算。
  • NTILE()CUME_DIST() 是分布分析的利器,适合用户分层和分位排名场景。

标签:窗口,进阶,OVER,id,amount,user,SQL,ORDER
From: https://blog.csdn.net/u012561308/article/details/144820274

相关文章

  • 掌握 PostgreSQL 的 psql 命令行工具
    title:掌握PostgreSQL的psql命令行工具date:2024/12/30updated:2024/12/30author:cmdragonexcerpt:psql是PostgreSQL关系数据库管理系统的交互式命令行工具,是数据库管理员和开发人员进行数据库管理和操作的主要接口。熟练使用psql工具,不仅能够提高对Postgre......
  • Python 进阶:深入理解 import 机制与 importlib 的妙用
    大家好,今天我们来深入探讨Python中的导入机制和importlib模块。相信不少朋友和我一样,平时写代码时可能只用过最基础的import语句,或者偶尔用importlib.import_module来做些动态导入。但其实这背后的机制非常有趣,而且importlib提供的功能远比我们想象的要丰富。Python的......
  • MySQL开源30年了(1995-2025)来自社区团队成员的特别祝福
     在MySQL圣诞倒计时即将结束之际,让我宣布(或提醒您)MySQL将在明年迎来30岁的生日!!MySQL的第一个版本于1995年发布,距今已有三十年。那个数据库后来演变成了MySQL,这个开源关系型数据库管理系统从那时起就改变了开发人员构建和扩展应用程序的方式。今天,在我们准备迎接MySQ......
  • 基于Redis有序集合实现滑动窗口限流
    滑动窗口算法是一种基于时间窗口的限流算法,它将时间划分为若干个固定大小的窗口,每个窗口内记录了该时间段内的请求次数。通过动态地滑动窗口,可以动态调整限流的速率,以应对不同的流量变化。整个限流可以概括为两个主要步骤:统计窗口内的请求数量应用限流规则Redis有序集合每个......
  • Python+Django大学生入伍人员管理系统--(Pycharm Flask Django Vue mysql)
    收藏关注不迷路!!需要的小伙伴可以发链接或者截图给我项目介绍大学生入伍人员管理系统的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品,体验高科技时代带给人们的方便,同时也能让用户体会到与以往常规产品不同的体验风格。......
  • Python+Django家政服务预约系统\搬家服务预约系统--(Pycharm Flask Django Vue mysql
    收藏关注不迷路!!需要的小伙伴可以发链接或者截图给我项目介绍基于Python+Django的家政保洁预约服务平台的开发背景,深植于现代生活节奏的加快、消费习惯的变化以及数字化转型的浪潮之中在快节奏的现代生活中,越来越多的家庭面临着工作与家庭生活的双重压力。传统的家庭清洁、......
  • Python+Django宠物援助平台\宠物领养系统\宠物服务寻找丢失宠物--(Pycharm Flask Dj
    收藏关注不迷路!!需要的小伙伴可以发链接或者截图给我项目介绍基于Python+Django的流浪动物宠物救助援助平台的开发背景,深刻反映了当代社会对动物福利的关注提升、技术进步的赋能作用,以及社会公益需求的日益增长。近年来,随着社会的进步和人们文化素质的提高,越来越多的公众开......
  • java.sql.SQLException: ORA-00600: 内部错误代码, 参数: [kcbnew_3]的其中一个解决方
    java.sql.SQLException:ORA-00600:内部错误代码,参数:[kcbnew_3]的其中一个解决方法 重启重启重启oracle服务。今天反馈添加数据库报错。试了一下就几各别的表不能插入。别的表好好的 GPT一下并检查了表空间都没什么问题。执行INSERTINTODEVICE_CONTROL(id,........
  • 直接调用文件设置qt可执行程序的图标,运行时的图标,exe本身的图标,以及固定到任务栏时的
    //设置应用程序图标(窗口图标和任务栏图标)this->setWindowIcon(QIcon("./Icon/ReadADtool.ico"));//从资源文件中加载图标  固定到任务栏上时的图标:在pro文件添加如下指令:    设置rc文件内容:IDI_ICON1ICONDISCARDABLE"ReadADtoo......
  • MySQL索引优化:提升查询性能的秘诀
    MySQL作为最流行的关系型数据库之一,索引是其性能优化的核心技术之一。合理地设计和使用索引,可以显著提高查询效率。然而,不当使用索引也可能带来性能问题。本文将介绍MySQL索引的基本概念、常见的索引类型及其应用场景,同时提供索引优化的最佳实践。......