如何计算相邻月份的销售额差值?SQL查询求助
按月汇总销售额并计算相邻月份差值的SQL修正
原始销售数据
| 日期 | 销售额 |
|---|---|
| 3/1/2023 | 800 |
| 3/2/2023 | 300 |
| 3/3/2023 | 500 |
| 4/1/2023 | 300 |
| 4/2/2023 | 500 |
| 4/3/2023 | 200 |
| 5/1/2023 | 100 |
| 5/2/2023 | 400 |
| 5/3/2023 | 400 |
期望输出结果
| 日期 | 销售额 | 差值 |
|---|---|---|
| 5/1/2023 | 900 | 100 |
| 4/1/2023 | 1000 | 600 |
| 3/1/2023 | 1600 | 0 |
现有查询语句
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, Salesdate), 0) AS TrendStartDate, SUM(Sales) AS TotalSales , LEAD(SUM(Sales), 1) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Salesdate), 0) ORDER BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Salesdate), 0) DESC) AS Sales_diff FROM salestable GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Salesdate), 0) ORDER BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Salesdate), 0) ASC
问题分析
原查询存在两个核心问题:
- 错误的分区设置:
PARTITION BY DATEADD(...)会将每个单独的月份作为一个分区,导致LEAD函数无法跨月份获取相邻值,每个分区仅一行数据,LEAD返回NULL。 - 排序与差值逻辑不匹配:原查询按日期升序排列,未实现“当前月销售额 - 下月销售额”的计算逻辑,也未处理最老月份的差值默认值。
修正后的查询语句
WITH MonthlySales AS ( -- 按月汇总销售额,得到每个月的起始日期和总销售额 SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, Salesdate), 0) AS TrendStartDate, SUM(Sales) AS TotalSales FROM salestable GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Salesdate), 0) ) SELECT -- 转换日期格式为MM/DD/YYYY,匹配期望输出 CONVERT(VARCHAR(10), TrendStartDate, 101) AS 日期, TotalSales AS 销售额, -- 计算当前月与下月的销售额差值,最老月份差值设为0 ISNULL(TotalSales - LEAD(TotalSales) OVER (ORDER BY TrendStartDate DESC), 0) AS 差值 FROM MonthlySales -- 按日期降序排列,得到期望的输出顺序 ORDER BY TrendStartDate DESC;
修正说明
- 用CTE拆分逻辑,先完成按月汇总,再计算差值,提升代码可读性。
- 移除
PARTITION BY,让LEAD在所有月份的结果集中生效,正确获取相邻月份的销售额。 - 通过
ORDER BY TrendStartDate DESC让LEAD返回下一个更早的月份销售额,结合TotalSales - LEAD(...)得到所需差值。 - 用
ISNULL处理无后续月份的情况,将差值设为0。 - 转换日期格式以匹配期望输出样式,最终按日期降序排列结果。
内容的提问来源于stack exchange,提问作者ram
相关产品推荐
相关产品推荐

