Sql server查询汇总补缺月份

发布于:2025-07-30 ⋅ 阅读:(18) ⋅ 点赞:(0)

Excel做图表的时候,如果你坐标是日期的时候,它会自动给你在图标上给你补全日期,这个有人喜欢有人忧,不过我忧的不是在Excel中,我忧的是要在Appsmith中的图表中显示连续的月份,希望在sql server查询中要补全缺失的月份。

一.需求:通过销售表汇总出来的数据为
月份          次数
1/2025     100
2/2025     300
4/2025     200
6/2025       50
在图表上我们希望显示的柱状图中这些缺失的月份需要用0补全,显示的数据为本月之前的连续12个月。


二.解法一:先汇总残缺数据再补全
先Sql Query汇总获取数据,然后JS再遍历补齐空缺,觉得太麻烦,放弃。


三.解法一:自定义月份表
定义一个序列表 MonthTable(01,02,03,04, 05,06,07,08,09,10,11,12),字段名为TMONTH,然后通过not in 补齐,因为会跨年,所以高于本月,年份就是取去年。
DECLARE
 -- 结束日期(默认当前日期)
@EndDate DATE = GETDATE(), 
--当前月份
@CurrentM TINYINT =MONTH(GETDATE()),
--去年
@LastY INT = YEAR(GETDATE())-1
-- 计算开始日期(结束日期往前推11个月)
DECLARE @StartDate DATE = DATEADD(MONTH, -11, @EndDate);

--合并
SELECT T.YearMonthSort,T.TotalCount FROM 
(
--先汇总
   ( SELECT 
        FORMAT(SaleDate, 'MM/yyyy') AS YearMonthSort,
        COUNT(1) AS TotalCount
    FROM Sales 
    WHERE SaleDate BETWEEN @StartDate AND @EndDate
    GROUP BY FORMAT(SaleDate, 'MM/yyyy')
   )
UNION ALL
--补缺月份数据
(
SELECT CASE WHEN TMONTH>@CurrentM THEN CAST(TMONTH AS VARCHAR)+'/'+CAST(@LastY AS VARCHAR) ELSE  CAST(TMONTH AS VARCHAR)+'/'+CAST(YEAR(GETDATE()) AS VARCHAR)   END AS  YearMonthSort ,
           0 AS TotalCount
           FROM  MonthTable 
           WHERE TMONTH NOT IN (SELECT DISTINCT MONTH(SaleDate) FROM Sales)
)  
) T ORDER BY T.YearMonthSort

四.解法三公用表表达式(CTE)
WITH cte_name (column_name1, column_name2, ...)
AS
(
CTE_query_definition
)
SELECT * FROM cte_name;

其实原理和自定义类似,定义的是一个临时命名的结果集,供后续查询使用,不需要一个自定义的实体表。
DECLARE 
    @EndDate DATE = GETDATE(), -- 结束日期(默认当前日期)
    @MonthCount Tinyint = 12 ;  --12个月
-- 计算开始日期(结束日期往前推11个月)
DECLARE @StartDate DATE = DATEADD(MONTH, -11, @EndDate);

-- 生成连续月份序列的CTE
;WITH MonthSeries AS (
    SELECT TOP (@MonthCount)
        DATEADD(MONTH, ROW_NUMBER() OVER(ORDER BY object_id) - 1, @StartDate) AS MonthStart
    FROM sys.all_objects
),
YearMonthSeries AS (
    SELECT 
        FORMAT(MonthStart, 'yyyyMM') AS YearMonthSort,
        FORMAT(MonthStart, 'MM/yyyy') AS YearMonthDisplay
    FROM MonthSeries
),
-- 业务数据汇总
BusinessData AS (
    SELECT 
        FORMAT(SaleDate, 'yyyyMM') AS YearMonthSort,
        count(1) AS TotalCount
    FROM Sales
    WHERE SaleDate BETWEEN @StartDate AND @EndDate
    GROUP BY FORMAT(SaleDate, 'yyyyMM')
)
-- 最终结果(确保连续12个月)
SELECT 
    y.YearMonthDisplay AS [年月],
    ISNULL(b.TotalCount, 0) AS [销售次数]
FROM YearMonthSeries y
LEFT JOIN BusinessData b ON y.YearMonthSort = b.YearMonthSort
ORDER BY y.YearMonthSort;

其实自己喜欢第二个方法,直接简单,不过方法三看起来专业,练练CTE才用方法三,。


网站公告

今日签到

点亮在社区的每一天
去签到