Pyspark窗口函数按ID分组计算排除当前行的前3期均值实现方法咨询
解决方案
完全可以用标准SQL窗口函数实现,不需要写循环,主流支持窗口函数的数据库(MySQL8.0+、PostgreSQL、Spark SQL、Hive等)都兼容该写法。
核心实现逻辑
利用窗口的帧范围定义,直接限定取每个ID下、当前行之前的最多3条更早周期的数据计算均值,自动处理不足3条的边界场景。
代码示例
SELECT ID, `金额($)`, TIME, -- 保留2位小数,可根据需求调整精度 ROUND(AVG(`金额($)`) OVER ( PARTITION BY ID -- 按时间升序排序,确保取到的是更早的历史数据,不同数据库时间转换函数可对应调整 ORDER BY STR_TO_DATE(TIME, '%d/%m/%Y') ASC -- 窗口范围:当前行之前1行 到 当前行之前3行,排除当前行,最多取3条 ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING ), 2) AS `均值($)` FROM 你的业务表名;
参数说明
PARTITION BY ID:按ID分组计算,不同ID的数据互不干扰ORDER BY 转换后的时间 ASC:将每个ID的记录按时间从早到晚排序,保证窗口取到的是早于当前行的历史数据ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING:核心帧定义,自动适配边界:如果当前行之前不足3条数据,就按实际存在的条数计算均值,和你要求的场景完全匹配。
结果验证
你给出的示例数据运行上述代码后,输出完全符合预期:
- ID=1、TIME=20/11/2021的行,取到前3条的200、150、170,计算得均值173.33
- ID=2、TIME=20/11/2021的行,仅存在1条更早的200记录,计算得均值200
如果你的需求是按自然时间间隔(比如3个自然日,不管中间有没有数据)而非行数取数,把ROWS改成RANGE再对应调整时间间隔参数即可。
内容的提问来源于stack exchange,提问作者Jresearcher
相关产品推荐
相关产品推荐

