SQL日期计算异常:应返回12/20/17却返回12/20/18,特定日期失效求助
SQL日期计算异常问题分析与修复
我来帮你揪出这个日期计算的bug!你的问题出在用字符串拼接构造日期时,错误地混用了不同日期的年份和月份,导致跨年度时出现年份偏移。
问题根源拆解
当@TODAYS_DT = '4/10/2018'时:
DATEADD(DAY, -75, '4/10/2018')得到的基准日期是2018-01-26- 你计算
@START_DT时,取的是这个基准日期的年份(2018),但DATEADD(MM, -1, 2018-01-26)得到的是2017-12-26,对应的年份应该是2017,不是2018 - 之前2/10/18、3/10/18正常是因为:减75天后的日期还在2017年,
DATEADD(MM,-1)后的年份和基准日期年份一致,拼接不出错;但4/10/18减75天跨到了2018年1月,这时候年份就不匹配了,导致生成了错误的12/20/18。
修复方案:避免字符串拼接日期
永远不要手动拼接字符串生成日期,用SQL内置的日期函数直接构造准确的日期,再按需转换格式。
方案1:使用DATEFROMPARTS(SQL Server 2012+支持)
DECLARE @TODAYS_DT DATE = '4/10/2018' DECLARE @BASE_DT DATE = DATEADD(DAY, -75, @TODAYS_DT) -- 生成基准日期上月的20日 DECLARE @START_DT DATE = DATEFROMPARTS( DATEPART(YEAR, DATEADD(MONTH, -1, @BASE_DT)), DATEPART(MONTH, DATEADD(MONTH, -1, @BASE_DT)), 20 ) -- 生成基准日期当月的20日 DECLARE @END_DT DATE = DATEFROMPARTS( DATEPART(YEAR, @BASE_DT), DATEPART(MONTH, @BASE_DT), 20 ) -- 转换为MM/DD/YYYY格式的字符串 SELECT CONVERT(CHAR(10), @START_DT, 101) AS START_DT, CONVERT(CHAR(10), @END_DT, 101) AS END_DT
方案2:兼容旧版SQL Server(2008及更早)
如果你的环境不支持DATEFROMPARTS,可以用日期偏移的方式构造:
DECLARE @TODAYS_DT DATE = '4/10/2018' DECLARE @BASE_DT DATE = DATEADD(DAY, -75, @TODAYS_DT) -- 上月20日:先跳转到上月1日,再加19天 DECLARE @START_DT DATE = DATEADD(DAY, 19, DATEADD(MONTH, DATEDIFF(MONTH, 0, @BASE_DT) - 1, 0)) -- 当月20日:先跳转到当月1日,再加19天 DECLARE @END_DT DATE = DATEADD(DAY, 19, DATEADD(MONTH, DATEDIFF(MONTH, 0, @BASE_DT), 0)) -- 转换为目标格式 SELECT CONVERT(CHAR(10), @START_DT, 101) AS START_DT, CONVERT(CHAR(10), @END_DT, 101) AS END_DT
这两种方案都会准确生成你需要的12/20/17和1/20/18,再也不会出现跨年度的日期错误。
内容的提问来源于stack exchange,提问作者Steve Tucker
相关产品推荐
相关产品推荐

