获取员工的生日 +-30 天

Get Birthdates of employees for a period of +-30 days

我是 SQL 的新手。对于我的 SAP 附加组件,我需要一个 SQL 查询来显示员工的生日 +-30 天(这将是最后给定 int 的用户)。我根据自己的理解写了一个查询,它只限制了当月的时间段。 Ex:If 当前日期是 2016.01.15 正确的查询应该显示出生日期在 12 月 16 日到 2 月 14 日之间。但是我只看到January.You的生日可以看到下面的查询

SELECT T0.[BirthDate], T0.[CardCode], T1.[CardName], T0.[Name], T0.[Tel1], 
T0.[E_MailL] FROM OCPR T0 INNER JOIN OCRD T1 ON T0.CardCode = T1.CardCode 
WHERE DATEADD( Year, DATEPART( Year, GETDATE()) - DATEPART( Year, T0.[BirthDate]), 
T0.[BirthDate]) BETWEEN CONVERT( DATE, GETDATE()-30)AND CONVERT( DATE, GETDATE() +30); 

我应该做哪些更改才能获得正确的结果? 任何帮助将不胜感激! :-)

我对此进行了一些简化。我已经在进行计算的代码中添加了注释,以便将来回顾时您会知道它在做什么(通常是救世主):)。

SELECT T0.[BirthDate], 
       T0.[CardCode], 
       T1.[CardName], 
       T0.[Name], 
       T0.[Tel1], 
       T0.[E_MailL]
FROM OCPR T0 
INNER JOIN OCRD T1 
ON T0.CardCode = T1.CardCode 
WHERE T0.[BirthDate] >= GETDATE()       -- Where the birthday is greater than or equal to today's date
AND   T0.[BirthDate] <= GETDATE() + 30  -- Where the birthday is less than or equal to today's date plus 30 days.

这样的事情怎么样:

SELECT T0.[BirthDate], T0.[CardCode], T1.[CardName], T0.[Name], T0.[Tel1], T0.[E_MailL] 
FROM OCPR T0 INNER JOIN OCRD T1 ON T0.CardCode = T1.CardCode 
WHERE TO.[BirthDate] BETWEEN DATEADD(DAY, -30, GETDATE()) AND DATEADD(DAY, +30, GETDATE()) 

您可以在评论中修改answer I've referenced如下:

SELECT T0.[BirthDate], T0.[CardCode], T1.[CardName], T0.[Name], T0.[Tel1], T0.[E_MailL]
FROM OCPR T0 INNER JOIN OCRD T1 ON T0.CardCode = T1.CardCode
WHERE 1 = (FLOOR(DATEDIFF(dd,TO.Birthdate,GETDATE()+30) / 365.25))
          -
          (FLOOR(DATEDIFF(dd,TO.Birthdate,GETDATE()-30) / 365.25))

根据 Vladimir 的评论,如果需要,您可以将“365.25”修改为“365.2425”以获得更高的准确性。

我在SQL服务器上测试过,因为它有DATEADDGETDATE的功能。

当 +-30 天的范围跨越 1 月 1 日时,即当范围属于两年时,您的查询 returns 错误结果。

你的计算

DATEADD(Year, DATEPART(Year, GETDATE()) - DATEPART( Year, T0.[BirthDate]), T0.[BirthDate])

BirthDate 的年份移动到与 GETDATE 相同的年份,因此如果 GETDATE returns 2016-01-01,则 BirthDate=1957-12-25 变成 2016-12-25。但是你的范围是从2015-12-012016-01-30,调整后的BirthDate不在其中。

有很多方法可以考虑这一年界线。

一个可能的变体是不从 2015-12-012016-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)@CurrDateBirthDate

之间的年差

DATEADD(year, DATEDIFF(year, @CurrDate, BirthDate), @CurrDate) @CurrDateBirthDate

同年搬入

最后的DATEADD(day, -@VarDays, ...)DATEADD(day, +@VarDays, ...)的范围为+-@VarDays

此范围在 "main" 以及之前和之后的年份创建了三次。

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 |
+------------+

您可以尝试使用 DAYOFYEAR:

SELECT T0.[BirthDate], 
       T0.[CardCode], 
       T1.[CardName], 
       T0.[Name], 
       T0.[Tel1], 
       T0.[E_MailL]
FROM OCPR T0 
INNER JOIN OCRD T1 
ON T0.CardCode = T1.CardCode
WHERE IF(DayOfYear(T0.[BirthDate]) - DayOfYear(CURDATE()) < 0, DayOfYear(T0.[BirthDate]) - DayOfYear(CURDATE()) + DayOfYear(DATE_FORMAT(CURDATE(),"%Y-12-31")), DayOfYear(T0.[BirthDate]) - DayOfYear(CURDATE())) <= 30
OR IF(DayOfYear(CURDATE()) - DayOfYear(T0.[BirthDate]) < 0, DayOfYear(CURDATE()) - DayOfYear(T0.[BirthDate]) + DayOfYear(DATE_FORMAT(CURDATE(),"%Y-12-31")), DayOfYear(CURDATE()) - DayOfYear(T0.[BirthDate])) <= 30