SQL每日记录统计:如何包含无记录日期并显示0值?
解决SQL统计补全无记录日期显示0的问题
嗨,这个需求我太熟了!你的原查询只会返回有符合条件记录的日期,要把过去90天里所有日期都列出来(哪怕当天没记录也显示0),关键是先造一个连续的日期序列,再和你的统计结果做左连接就行。下面是具体的修改方案:
核心思路
- 用递归CTE生成过去90天的每一天(从90天前的凌晨到今天凌晨)
- 将这个日期序列和你原有的统计查询做左连接,确保每个日期都被保留
- 对没有匹配到记录的日期,统计数自动显示为0
修改后的完整SQL语句
WITH DateRange AS ( -- 起始日期:90天前的凌晨 SELECT DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 90, 0) AS DateValue UNION ALL -- 递归生成后续每天的日期,直到今天 SELECT DATEADD(day, 1, DateValue) FROM DateRange WHERE DateValue < DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0) ) SELECT CONVERT(VARCHAR, dr.DateValue, 101) AS "Date", COUNT(r.result_ID) AS "Results" FROM DateRange dr LEFT JOIN Results r ON CONVERT(VARCHAR, r.CreatedDate, 101) = CONVERT(VARCHAR, dr.DateValue, 101) AND r.Verified = 1 AND r.CreatedDate >= DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 90, 0) GROUP BY CONVERT(VARCHAR, dr.DateValue, 101) ORDER BY "Date" DESC OPTION (MAXRECURSION 0); -- 避免递归次数限制(生成90天日期其实没超默认限制,加这个更稳妥)
关键细节说明
- 递归CTE(DateRange):从90天前的日期开始,每天加1生成到今天的所有日期,保证没有遗漏的日期节点。
- 左连接(LEFT JOIN):用日期序列表左连接你的Results表,这样即使某一天没有符合条件的记录,日期也会被保留在结果里。
- WHERE条件移到JOIN里:原来的WHERE条件如果放在外层,会把左连接后的空值行过滤掉,所以要把
Verified=1和日期范围条件放到JOIN的ON子句中,确保只匹配符合条件的记录,同时保留所有日期。 - MAXRECURSION选项:SQL Server默认递归次数限制是100,这里生成90天的日期虽然没超过,但加上
OPTION (MAXRECURSION 0)可以避免意外的递归次数错误。
内容的提问来源于stack exchange,提问作者Joe Taberna
相关产品推荐
相关产品推荐

