用SQL实现三次指数平滑预测:递归与非递归两种解法详解

目录

一、三次指数平滑法基础

1.1 核心原理

1.2 数据源说明

二、解法一:递归CTE实现

2.1 完整代码

2.2 关键解析

三、解法二:非递归(LAG窗口函数)实现

3.1 完整代码

3.2 关键解析

四、两种解法对比

五、实战注意事项

六、总结


在时间序列预测领域,三次指数平滑法是处理非线性趋势数据的经典方法,广泛应用于零售额、销量、产值等经济数据的预测。相比于Python/R等数据分析语言,SQL作为数据存储与处理的核心工具,直接在数据库中实现该算法可减少数据迁移成本。本文将以“1960-1982年全国社会商品零售额预测”为例,详解递归CTE非递归(LAG窗口函数)两种SQL实现方式,覆盖核心逻辑、完整代码与实战解析。

一、三次指数平滑法基础

1.1 核心原理

三次指数平滑法通过对原始数据进行三次加权平滑,拟合非线性趋势,核心公式如下(平滑系数α通常取0.1~0.3,本文取0.3):

1.2 数据源说明

本文使用1960-1982年全国社会商品零售额数据(单位:亿元),目标是预测1983年(m=1)和1985年(m=3)的零售额,原始数据如下(注:1972/1975年数据疑似笔误,保留原始值):

年份196019611962...198019811982
零售额696.6607.7604.0...2140.02350.02570.0

二、解法一:递归CTE实现

递归CTE(WITH RECURSIVE)是处理“递推依赖”问题的经典方式,适合MySQL 8.0+/PostgreSQL等支持递归的数据库,核心思路是通过“初始值+递推逻辑”逐期计算平滑值。

2.1 完整代码

-- 1. 创建并插入原始数据 CREATE TABLE IF NOT EXISTS retail_sales ( year INT PRIMARY KEY, -- 年份 sales DECIMAL(10,1) -- 社会商品零售额(亿元) ); ​ INSERT INTO retail_sales (year, sales) VALUES (1960, 696.6), (1961, 607.7), (1962, 604.0), (1963, 604.5), (1964, 638.2), (1965, 670.3), (1966, 732.8), (1967, 770.5), (1968, 737.3), (1969, 801.5), (1970, 858.0), (1971, 929.2), (1972, 10233.0), (1973, 1106.7), (1974, 1163.6), (1975, 12711.0), (1976, 1339.4), (1977, 1432.8), (1978, 1558.6), (1979, 1800.0), (1980, 2140.0), (1981, 2350.0), (1982, 2570.0); ​ -- 2. 递归CTE计算平滑值并预测 WITH RECURSIVE -- 步骤1:给数据编连续时间序号t sales_with_seq AS ( SELECT year, sales, ROW_NUMBER() OVER (ORDER BY year) AS t -- t=1对应1960,t=23对应1982 FROM retail_sales ), -- 步骤2:递归计算三次平滑值 smoothing_values AS ( -- 初始行(t=0,初始值=1960年零售额) SELECT 0 AS t, NULL AS year, NULL AS sales, (SELECT sales FROM sales_with_seq WHERE t=1) AS s1, (SELECT sales FROM sales_with_seq WHERE t=1) AS s2, (SELECT sales FROM sales_with_seq WHERE t=1) AS s3 UNION ALL -- 递推行(t≥1,逐期计算平滑值) SELECT sws.t, sws.year, sws.sales, ROUND(0.3 * sws.sales + 0.7 * sv.s1, 4) AS s1, -- 一次平滑 ROUND(0.3 * (0.3 * sws.sales + 0.7 * sv.s1) + 0.7 * sv.s2, 4) AS s2, -- 二次平滑 ROUND(0.3 * (0.3 * (0.3 * sws.sales + 0.7 * sv.s1) + 0.7 * sv.s2) + 0.7 * sv.s3, 4) AS s3 -- 三次平滑 FROM smoothing_values sv JOIN sales_with_seq sws ON sv.t + 1 = sws.t ), -- 步骤3:计算预测参数(取最后一期t=23的平滑值) forecast_params AS ( SELECT s1, s2, s3, ROUND(3*s1 - 3*s2 + s3, 4) AS a, ROUND((0.3 / (2 * POWER(0.7, 2))) * ((6 - 5*0.3)*s1 - 2*(5 - 4*0.3)*s2 + (4 - 3*0.3)*s3), 4) AS b, ROUND((POWER(0.3, 2) / (2 * POWER(0.7, 2))) * (s1 - 2*s2 + s3), 4) AS c FROM smoothing_values WHERE t = (SELECT MAX(t) FROM sales_with_seq) ) -- 步骤4:预测1983/1985年零售额 SELECT 1983 AS forecast_year, ROUND(a + b*1 + c*POWER(1,2), 4) AS forecast_sales FROM forecast_params UNION ALL SELECT 1985 AS forecast_year, ROUND(a + b*3 + c*POWER(3,2), 4) AS forecast_sales FROM forecast_params;

2.2 关键解析

  1. 数据编序:通过ROW_NUMBER()将年份转为连续索引t,解决“递推依赖”的时间基准问题;

  2. 递归逻辑

    1. 初始行(t=0):设定三次平滑的初始值均为1960年零售额;

    2. 递推行:通过JOIN关联“当前期t”与“前一期t-1”,代入公式计算当期平滑值;

  3. 预测参数:仅取最后一期(1982年,t=23)的平滑值计算a/b/c,避免冗余;

  4. 预测值:1983年对应步长m=1,1985年对应m=3,代入非线性预测公式。

三、解法二:非递归(LAG窗口函数)实现

对于不支持递归CTE的老版本数据库(如MySQL 5.x),可通过LAG窗口函数获取前一期平滑值,分步计算一次、二次、三次平滑值,核心思路是“分步拆解递推逻辑”。

3.1 完整代码

-- 1. 复用原始数据表(同解法一,省略创建/插入步骤) -- 2. 非递归计算平滑值并预测 WITH -- 步骤1:数据编序 sales_with_seq AS ( SELECT year, sales, ROW_NUMBER() OVER (ORDER BY year) AS t FROM retail_sales ), -- 步骤2:计算一次平滑值s1 s1_calc AS ( SELECT t, year, sales, CASE WHEN t = 1 THEN sales -- 第一行初始值 ELSE ROUND(0.3 * sales + 0.7 * LAG(s1) OVER (ORDER BY t), 4) END AS s1 FROM ( SELECT t, year, sales, CAST(NULL AS DECIMAL(10,4)) AS s1 FROM sales_with_seq ) tmp ), -- 步骤3:基于s1计算二次平滑值s2 s2_calc AS ( SELECT t, year, sales, s1, CASE WHEN t = 1 THEN s1 -- 第一行初始值 ELSE ROUND(0.3 * s1 + 0.7 * LAG(s2) OVER (ORDER BY t), 4) END AS s2 FROM ( SELECT t, year, sales, s1, CAST(NULL AS DECIMAL(10,4)) AS s2 FROM s1_calc ) tmp ), -- 步骤4:基于s2计算三次平滑值s3 s3_calc AS ( SELECT t, year, sales, s1, s2, CASE WHEN t = 1 THEN s2 -- 第一行初始值 ELSE ROUND(0.3 * s2 + 0.7 * LAG(s3) OVER (ORDER BY t), 4) END AS s3 FROM ( SELECT t, year, sales, s1, s2, CAST(NULL AS DECIMAL(10,4)) AS s3 FROM s2_calc ) tmp ), -- 步骤5:计算预测参数 forecast_params AS ( SELECT s1, s2, s3, ROUND(3*s1 - 3*s2 + s3, 4) AS a, ROUND((0.3 / (2 * POWER(0.7, 2))) * ((6 - 5*0.3)*s1 - 2*(5 - 4*0.3)*s2 + (4 - 3*0.3)*s3), 4) AS b, ROUND((POWER(0.3, 2) / (2 * POWER(0.7, 2))) * (s1 - 2*s2 + s3), 4) AS c FROM s3_calc WHERE t = (SELECT MAX(t) FROM sales_with_seq) ) -- 步骤6:预测结果 SELECT 1983 AS forecast_year, ROUND(a + b*1 + c*POWER(1,2), 4) AS forecast_sales FROM forecast_params UNION ALL SELECT 1985 AS forecast_year, ROUND(a + b*3 + c*POWER(3,2), 4) AS forecast_sales FROM forecast_params;

3.2 关键解析

  1. 分步计算:将三次平滑拆分为三个CTE,先算一次平滑,再基于一次结果算二次,最后算三次,逻辑更直观;

  2. LAG函数:通过LAG(s1) OVER (ORDER BY t)获取前一期的一次平滑值,替代递归的“前一期关联”;

  3. 初始值处理:每一级平滑的第一行直接取初始值,后续行通过LAG递推,与递归解法保持一致。

四、两种解法对比

维度递归CTE解法非递归(LAG)解法
适配数据库MySQL 8.0+/PostgreSQL/PGMySQL 5.7+/PostgreSQL/PG(支持LAG)
代码简洁性代码更紧凑,一步完成递推代码分步拆解,步骤更多
可读性递推逻辑集中,适合熟悉递归的开发者分步清晰,新手更容易理解
调试难度需整体调试递归逻辑可单独查看每一级平滑值,易调试
性能数据量小时无差异,大数据量略优数据量小时无差异,步骤多但无性能损耗
适用场景支持递归的新版本数据库老版本数据库(无递归CTE)

五、实战注意事项

  1. 平滑系数α调整:α越小,平滑效果越强(更依赖历史数据);α越大,对近期数据越敏感。可通过“误差最小化”(如RMSE)调整α值;

  2. 异常数据处理:本文1972/1975年数据明显异常,实际应用中需先清洗(如修正笔误、剔除异常值);

  3. 预测步长:三次指数平滑适合短期预测(m≤5),步长过大会导致预测误差显著增加;

  4. 结果验证:两种解法的预测结果完全一致,可互相验证正确性。

六、总结

本文以“社会商品零售额预测”为例,实现了三次指数平滑法的两种SQL解法:递归CTE适合新版本数据库,代码紧凑;非递归(LAG)解法适配性更广,逻辑更直观。两种解法均遵循“初始值设定→逐期递推平滑值→计算预测参数→推导预测值”的核心流程,可直接复用至销量、产值等时间序列预测场景。

在实际应用中,可根据数据库版本选择解法,并结合业务场景调整平滑系数、清洗异常数据,以提升预测准确性。SQL作为数据处理的核心工具,直接实现时间序列算法可最大化利用数据库的存储与计算能力,减少数据迁移成本,是数据分析工程师的必备技能。

往期精彩

SQL进阶技巧:车辆班次问题分析_sql进阶技巧:车辆班次问题分析-CSDN博客

SQL 进阶技巧:断点重分组应用求连续段的最后一个数及每段的个数【拼多多面试题】_hql面试题46【拼多多面试题】-CSDN博客

SQL腾讯面试真题:玩家战败场次中点位占领统计问题-CSDN博客

面试提问:SQL 查询无数据时如何强制返回一行 0 | 通用兜底方案全解析_sql查询不到数据返回默认值-CSDN博客

SQL面试题:计算订单转化率和复购率(阿里数据分析一面)_sql计算复购率-CSDN博客

面试提问:数据开发中如何通过指标拆解来指导SQL编写?(附拆解模板)_根据指标维度来生成sql-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1165425.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全网最全本科生必用TOP10 AI论文网站测评

全网最全本科生必用TOP10 AI论文网站测评 2026年本科生学术写作工具测评:为何需要一份权威榜单? 随着人工智能技术在教育领域的深入应用,越来越多的本科生开始依赖AI论文网站提升写作效率和质量。然而,面对市场上五花八门的工具&a…

django基于python的旅游个性化定制平台的设计与实现

目录摘要关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!摘要 随着旅游业的快速发展,个性化旅游定制需求日益增长。传统的旅游平台往往提供标准化产品,难以满…

隐私计算新范式:基于联邦学习的大数据解决方案

隐私计算新范式:基于联邦学习的大数据解决方案 关键词:隐私计算、联邦学习、数据安全、分布式训练、大数据协同 摘要:在数据成为“新型石油”的今天,如何在不泄露隐私的前提下实现数据价值的协同挖掘,是全球企业和科研机构面临的核心挑战。本文将以“联邦学习”这一隐私计…

一文读懂集群与分布式:两种核心服务器架构的本质差异

在互联网技术飞速发展的今天,我们日常使用的购物 App、短视频平台、在线办公工具等,背后都离不开庞大的服务器体系作为支撑。当业务规模不断扩大,单一服务器的性能、并发能力和稳定性逐渐达到瓶颈时,“集群”和“分布式”这两种架…

django基于python的旅游服务管理系统

目录 Django 基于 Python 的旅游服务管理系统摘要 关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! Django 基于 Python 的旅游服务管理系统摘要 旅游服务管理系统旨在通过信息化手…

主流深度学习框架全景对比:PyTorch、TensorFlow、JAX的发展、特性与工程落地

深度学习框架是AI研发的“基础设施”,不同框架的设计哲学、技术特性与生态适配性,直接决定了研发效率、工程落地难度和性能表现。本文系统梳理PyTorch、TensorFlow、JAX三大主流框架的发展脉络,拆解核心特性差异,并结合实际工程场…

django基于python的流浪宠物领养管理系统

目录Django 基于 Python 的流浪宠物领养管理系统摘要关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!Django 基于 Python 的流浪宠物领养管理系统摘要 随着城市化进程加快&#xff…

学霸同款8个AI论文平台,本科生轻松搞定毕业论文!

学霸同款8个AI论文平台,本科生轻松搞定毕业论文! AI 工具如何助力论文写作? 在当今学术研究日益复杂的背景下,越来越多的本科生开始借助 AI 工具来提升论文写作效率。这些工具不仅能帮助学生快速生成内容,还能有效降…

开发基于大模型的金融专业教材章节总结生成器

开发基于大模型的金融专业教材章节总结生成器 关键词:大模型、金融专业教材、章节总结生成器、自然语言处理、文本生成 摘要:本文旨在详细阐述开发基于大模型的金融专业教材章节总结生成器的全过程。从背景介绍入手,深入探讨核心概念、算法原理、数学模型等内容,通过项目实…

Java--打印流

基本介绍在整个IO包中,打印流是输出信息做方便的类,主要包含字节打印流(PrintStream)和字符打印流(PrintWriter)。打印流提供了非常方便的打印功能,可以打印任何的数据类型,例如:小数、整数、字符串等等代码说明PrintS…

AI Agent在风险管理中的应用

AI Agent在风险管理中的应用关键词:AI Agent、风险管理、智能决策、自动化、风险评估摘要:本文深入探讨了AI Agent在风险管理领域的应用。首先介绍了相关背景,包括目的、预期读者等内容。接着阐述了AI Agent和风险管理的核心概念及联系&#…

UE5 C++(33):单播代理,宏 DECLARE_DELEGATE_xParam(代理名,参数序列)。

(172)概念, 在 C 标准库的容器实现上,也使用了代理,迭代器的代理,该代理关联了容器与其上的迭代器 :(173)本类的初始状态 :(174)宏 DE…

提示工程架构师揭秘:提示工程如何重塑大数据分析生态

提示工程架构师揭秘:提示工程如何重塑大数据分析生态 1. 引入与连接:大数据分析师的“效率困境”与破局点 深夜十点,小张揉着发涩的眼睛盯着电脑屏幕——他是某零售企业的大数据分析师,今天的任务是分析“2023年双11期间华北地区母…

深度学习毕设项目:通过python-pytorch训练识别是否是积水区域

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

SEDA (Staged Event-Driven Architecture, 分阶段事件驱动架构

SEDA(Staged Event-Driven Architecture,分阶段事件驱动架构)是将复杂事件驱动应用拆解为多个通过队列连接的独立处理阶段,结合事件驱动与动态资源控制,以实现高并发、负载适配与模块化的架构范式,由 UC Be…

深入理解 Keepalive:从协议到 Nginx 实战(全场景解析)

在计算机网络与服务端开发中,keepalive 是一个高频出现但易被混淆的概念。它并非单一技术,而是贯穿不同层级(应用层、传输层)、适配多种场景的「连接保活与复用机制」。核心目标是避免频繁创建/销毁网络连接,降低系统开…

EMW3080的独立接口板

简 介: 本文介绍了基于EMW3080 WiFi模块的接口板设计与测试。设计目的是开发一款可直接通过串口连接单片机的WiFi接口板,采用单面PCB设计,通过快速制板方法完成。测试结果显示,预配置的EMW3080模块能自动接入WiFi并建立UDP广播通道…

厨房灵感不设限:cpolar内网穿透让 YunYouJun cook 从本地走向全网

YunYouJun/cook 的核心功能围绕 “随机菜谱推荐” 展开,用户可输入关键词(如 “素食”“10 分钟完成”)或筛选条件(如烹饪难度、可用厨具),快速获取适配的菜谱方案,同时支持用户提交自己的私房菜…

Reactor 多线程模型

我们来详细、系统地解读一下 Reactor 多线程模型。这是高性能网络编程中的核心架构模式,Nginx、Redis、Netty 等知名系统都基于此模型。一、核心思想:分而治之 事件驱动Reactor 模型的本质是将网络处理中的“事件”(如连接建立、数据到达、数…