我在 SQL Server 中对其进行了测试,因为它具有DATEADD、GETDATE 功能。
当 +-30 天的范围跨越 1 月 1 日时,即该范围属于两年时,您的查询返回错误的结果。
你的计算
DATEADD(Year, DATEPART(Year, GETDATE()) - DATEPART( Year, T0.[BirthDate]), T0.[BirthDate])
将BirthDate 的年份移动到与GETDATE 相同的年份,因此如果GETDATE 返回2016-01-01,则BirthDate=1957-12-25 变为2016-12-25。但是您的范围是从2015-12-01 到2016-01-30 并且调整后的BirthDate 不属于它。
有很多方法可以考虑到这一年的界限。
一种可能的变体是不将2015-12-01 到2016-01-30 的范围设为一个,而是将三个范围设为未来和前几年:
from `2014-12-01` to `2015-01-30`
from `2015-12-01` to `2016-01-30`
from `2016-12-01` to `2017-01-30`
还有一点注意——最好将原始BirthDate 与一些计算的结果进行比较,而不是转换BirthDate 并比较函数的结果。在第一种情况下优化器可以在BirthDate 上使用索引,在第二种情况下它不能。
这是我在 SQL Server 2008 中测试的完整示例。
DECLARE @T TABLE (BirthDate date);
INSERT INTO @T (BirthDate) VALUES
('2016-12-25'),
('2016-01-25'),
('2016-02-25'),
('2016-11-25'),
('2015-12-25'),
('2015-01-25'),
('2015-02-25'),
('2015-11-25'),
('2014-12-25'),
('2014-01-25'),
('2014-02-25'),
('2014-11-25');
--DECLARE @CurrDate date = '2016-01-01';
DECLARE @CurrDate date = '2015-12-31';
DECLARE @VarDays int = 30;
我使用变量@CurrDate 而不是GETDATE 来检查它在不同情况下的工作方式。
DATEDIFF(year, @CurrDate, BirthDate) 是@CurrDate 和BirthDate 之间的年份差
DATEADD(year, DATEDIFF(year, @CurrDate, BirthDate), @CurrDate) 是@CurrDate 与BirthDate 移入同一年
最后的DATEADD(day, -@VarDays, ...) 和DATEADD(day, +@VarDays, ...) 构成+-@VarDays 的范围。
此范围针对“主要”以及上一年和下一年创建了 3 次。
SELECT
BirthDate
FROM @T
WHERE
(
BirthDate >= DATEADD(day, -@VarDays, DATEADD(year, DATEDIFF(year, @CurrDate, BirthDate), @CurrDate))
AND
BirthDate <= DATEADD(day, +@VarDays, DATEADD(year, DATEDIFF(year, @CurrDate, BirthDate), @CurrDate))
)
OR
(
BirthDate >= DATEADD(day, -@VarDays, DATEADD(year, DATEDIFF(year, @CurrDate, BirthDate)+1, @CurrDate))
AND
BirthDate <= DATEADD(day, +@VarDays, DATEADD(year, DATEDIFF(year, @CurrDate, BirthDate)+1, @CurrDate))
)
OR
(
BirthDate >= DATEADD(day, -@VarDays, DATEADD(year, DATEDIFF(year, @CurrDate, BirthDate)-1, @CurrDate))
AND
BirthDate <= DATEADD(day, +@VarDays, DATEADD(year, DATEDIFF(year, @CurrDate, BirthDate)-1, @CurrDate))
)
;
结果
+------------+
| BirthDate |
+------------+
| 2016-12-25 |
| 2016-01-25 |
| 2015-12-25 |
| 2015-01-25 |
| 2014-12-25 |
| 2014-01-25 |
+------------+