SQL Server中两个日期范围的n日对应值对比实现问题
问题分析与解决方案
你的核心问题在于关联条件选错了逻辑:原来用DATEADD(day, 1, pre.[date])是按日期的偏移量关联,但需求是两个日期范围内的第n天互相对比(不管两个日期范围的实际日期差多少),所以应该用「行号」来做关联依据,而不是日期本身的偏移。
修正思路
- 分别给当期、往期的日期数据按日期升序生成行号,行号就是该日期在对应范围里的「第n天」标识。
- 用行号作为关联条件,这样就能保证当期第1天对应往期第1天,第2天对应第2天,以此类推。
- 用
FULL OUTER JOIN覆盖两个范围长度不一致的情况,再用ISNULL处理缺失值为0或NULL。
修正后的SQL代码
DECLARE @currentStartDateTime datetime = '2018-02-04 00:00:00' DECLARE @currentEndDateTime datetime = '2018-02-07 23:59:59' DECLARE @previousStartDateTime datetime = '2018-01-01 00:00:00' DECLARE @previousEndDateTime datetime = '2018-01-03 23:59:59' SELECT ISNULL(cur.[date], NULL) AS [curDate], ISNULL(cur.[value], 0) AS [curValue], ISNULL(pre.[date], NULL) AS [preDate], ISNULL(pre.[value], 0) AS [preValue] FROM ( -- 给当期日期生成行号,按日期升序排序,行号=第n天 SELECT [date], [value], ROW_NUMBER() OVER(ORDER BY [date] ASC) AS day_num FROM [data] WHERE [date] BETWEEN @currentStartDateTime AND @currentEndDateTime ) cur FULL OUTER JOIN ( -- 给往期日期生成行号,按日期升序排序,行号=第n天 SELECT [date], [value], ROW_NUMBER() OVER(ORDER BY [date] ASC) AS day_num FROM [data] WHERE [date] BETWEEN @previousStartDateTime AND @previousEndDateTime ) pre ON cur.day_num = pre.day_num -- 核心:用行号关联,实现第n天对应 ORDER BY ISNULL(cur.day_num, pre.day_num) ASC -- 按行号排序,保证顺序正确
为什么这样能满足需求?
- 对于示例中的当期4天、往期3天:
- 当期行号1-4,往期行号1-3
- 行号1-3关联后,正常显示对应日期和值
- 行号4时,往期没有对应行,所以
preDate为NULL,preValue被ISNULL填充为0,完全符合你给出的期望输出。
- 当往期比当期长时,当期没有的行号会显示
curDate为NULL,curValue为0,同样满足规则。
内容的提问来源于stack exchange,提问作者pblyt
相关产品推荐
相关产品推荐

