在Microsoft SQL Server中计算5天前置期滚动销售总和的问题
解决SQL Server中5天前置期滚动销售总和计算问题
你的核心需求是:对每个日期,计算**当前日期前5天(不含当天)**的销售总和,比如6月15号要统计6月10日至14日的销量。原代码存在两个关键问题:
- 用
ROWS按行数计算范围,若日期不连续(如某天无销售),会导致统计的日期范围不准确; - 原窗口包含了当前行(当天)的销量,不符合你“前置期”的要求。
修正后的SQL代码(针对存在连续销售数据的场景)
SELECT TOP 100 DATEFROMPARTS(Year, Month, Day) AS Date, L.ItemCode, L.MinLeadTime, DD.Quantity, -- 统计当前日期前5天到前1天的销量总和 CAST(SUM(DD.Quantity) OVER ( PARTITION BY L.ItemCode ORDER BY DATEFROMPARTS(Year, Month, Day) RANGE BETWEEN INTERVAL 5 DAY PRECEDING AND INTERVAL 1 DAY PRECEDING ) AS DECIMAL(18,2)) AS [Rolling Sum Sales], L.ImpressLevel FROM -- 替换为你的实际关联表 YourMainTable L JOIN YourDetailTable DD ON L.ItemCode = DD.ItemCode
处理日期不连续的场景(某天无销售仍需显示滚动总和)
如果存在日期缺失的情况,需要先生成连续的日期序列,再与销售数据左连接,确保每个日期都能计算滚动总和:
-- 生成连续日期范围(替换为你的实际日期区间) WITH DateSeries AS ( SELECT CAST('2024-06-01' AS DATE) AS Date UNION ALL SELECT DATEADD(DAY, 1, Date) FROM DateSeries WHERE Date < CAST('2024-06-30' AS DATE) ), -- 按日期和商品汇总每日销量 DailySales AS ( SELECT DATEFROMPARTS(Year, Month, Day) AS Date, ItemCode, SUM(Quantity) AS Quantity FROM YourDetailTable GROUP BY DATEFROMPARTS(Year, Month, Day), ItemCode ) SELECT ds.Date, L.ItemCode, L.MinLeadTime, ISNULL(ds_sales.Quantity, 0) AS Quantity, CAST(SUM(ISNULL(ds_sales.Quantity, 0)) OVER ( PARTITION BY L.ItemCode ORDER BY ds.Date RANGE BETWEEN INTERVAL 5 DAY PRECEDING AND INTERVAL 1 DAY PRECEDING ) AS DECIMAL(18,2)) AS [Rolling Sum Sales], L.ImpressLevel FROM DateSeries ds CROSS JOIN (SELECT DISTINCT ItemCode, MinLeadTime, ImpressLevel FROM YourMainTable) L LEFT JOIN DailySales ds_sales ON ds.Date = ds_sales.Date AND L.ItemCode = ds_sales.ItemCode ORDER BY ds.Date, L.ItemCode OPTION (MAXRECURSION 0); -- 递归生成日期时需添加,避免递归次数限制
关键说明
- 使用
RANGE而非ROWS:RANGE基于日期值的范围计算,即使日期不连续,也能准确统计指定天数内的数据; - 调整窗口范围:
INTERVAL 5 DAY PRECEDING AND INTERVAL 1 DAY PRECEDING明确指定统计当前日期往前推5天到前1天的区间,排除当天数据; - 日期连续处理:通过递归CTE生成连续日期,再关联商品维度,确保每个日期-商品组合都有计算结果,无销售时销量显示为0。
内容的提问来源于stack exchange,提问作者Zuks
相关产品推荐
相关产品推荐

