SQL月度产品累计增长报表查询需求及问题求助
按公司统计月度累计产品数量的SQL查询问题
需求说明:
- 生成月度增长报表,按公司统计各年月度累计产品数量:若某公司上月累计产品数为4,本月新增1,则上月显示4,本月显示5(上月累计值+本月新增值),需覆盖所有年份。
现有问题:
已编写查询可按公司、年份、月份统计当月产品新增数量,但尝试用lag函数实现累计时结果不符合预期,需要实现同公司内1月累计值累加到2月,2月累计值再累加到3月的连续累加逻辑。
原始查询代码:
SELECT * FROM ( SELECT c.Name, YEAR(p.DateAdded) [Year], DATENAME(MONTH, p.DateAdded) [Month], COUNT(ProductID)--+lag(COUNT(p.ProductID),1) OVER ( ORDER BY YEAR(p.DateAdded),DATENAME(MONTH, p.DateAdded)) ProductCount FROM Product.Product p LEFT JOIN (SELECT ID,name from sourcing.Company WHERE CompanyTypeID=1 AND DateDeleted IS null) c ON p.ManufacturerID=c.id WHERE p.DateArchived IS NULL AND p.ManufacturerID=571 AND YEAR(p.DateAdded) IN ('2015') GROUP BY c.Name,YEAR(p.DateAdded), DATENAME(MONTH, p.DateAdded) ) AS MontlySalesData ORDER BY MontlySalesData.Year,MontlySalesData.Month
当前查询结果:
| 公司 | 年份 | 月份 | 产品数量 |
|---|---|---|---|
| Company1 | 2022 | 一月 | 5 |
| Company1 | 2022 | 二月 | 6 |
| Company2 | 2022 | 一月 | 5 |
| Company2 | 2022 | 二月 | 6 |
| Company3 | 2022 | 一月 | 5 |
| Company3 | 2022 | 二月 | 6 |
预期结果:
| 公司 | 年份 | 月份 | 产品数量 |
|---|---|---|---|
| Company1 | 2022 | 一月 | 5 |
| Company1 | 2022 | 二月 | 11 |
| Company2 | 2022 | 一月 | 5 |
| Company2 | 2022 | 二月 | 11 |
| Company3 | 2022 | 一月 | 5 |
| Company3 | 2022 | 二月 | 11 |
| Company3 | 2022 | 三月 | 13 |
| Company3 | 2022 | 四月 | 50 |
解决方案:使用SUM窗口函数实现累计计算
lag函数只能获取上一行的单个值,无法实现连续累加,正确的做法是使用SUM() OVER()窗口函数,按公司分区、按年月排序来计算累计值。
修改后的查询代码:
SELECT Name AS 公司, [Year] AS 年份, DATENAME(MONTH, DATEFROMPARTS([Year], MonthNum, 1)) AS 月份, CumulativeProductCount AS 产品数量 FROM ( SELECT c.Name, YEAR(p.DateAdded) AS [Year], MONTH(p.DateAdded) AS MonthNum, -- 用数字月份保证排序正确 COUNT(p.ProductID) AS MonthlyAddition, -- 按公司分区,按年份、数字月份排序,计算累计值 SUM(COUNT(p.ProductID)) OVER ( PARTITION BY c.Name ORDER BY YEAR(p.DateAdded), MONTH(p.DateAdded) ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS CumulativeProductCount FROM Product.Product p LEFT JOIN ( SELECT ID, name FROM sourcing.Company WHERE CompanyTypeID=1 AND DateDeleted IS NULL ) c ON p.ManufacturerID = c.id WHERE p.DateArchived IS NULL -- 移除单公司、单年份限制,覆盖所有公司和年份 GROUP BY c.Name, YEAR(p.DateAdded), MONTH(p.DateAdded) ) AS MonthlyData ORDER BY 公司, 年份, MonthNum
关键说明:
- 按公司分区:
PARTITION BY c.Name确保累计计算仅在同公司内进行,不会跨公司累加。 - 用数字月份排序:使用
MONTH(p.DateAdded)获取数字月份,避免DATENAME返回的月份字符串排序错误(比如"十月"会排在"二月"之前)。 - 累计窗口范围:
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW明确指定从当前分区的第一行到当前行进行累加,这是窗口函数累计的默认行为,显式写出更清晰。 - 移除不必要的筛选:原查询中的
ManufacturerID=571和YEAR(p.DateAdded) IN ('2015')限制了数据范围,若要覆盖所有公司和年份需移除。
执行该查询后,结果将符合预期的累计逻辑。
内容的提问来源于stack exchange,提问作者ArtiNgqobe
相关产品推荐
相关产品推荐

