获得员工的出生日期为-30天

时间:2016-01-15 09:18:27

标签: sql sap

我是SQL的新手。对于我的SAP附加组件,我需要一个SQL查询来显示员工的出生日期为+ -30天(这将是最后给出int的用户)。我根据自己的理解写了一个查询,它只限制了当月的周期。例如:如果当前日期是2016.01.15,则正确的查询应显示12月16日至2月14日期间的出生日期。但我只看到1月份的出生日期。你可以看到下面的查询。

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); 

为了获得正确的结果,我应该做些什么改变? 任何帮助将非常感谢! : - )

4 个答案:

答案 0 :(得分:1)

这样的事情怎么样:

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

根据弗拉基米尔的评论,您可以将“ 365.25 ”修改为“ 365.2425 ”,以便在需要时提高准确性。

答案 1 :(得分:1)

我在SQL Server中对其进行了测试,因为它具有DATEADDGETDATE函数。

当1到1天的范围为+ -30天时,即当范围属于两年时,您的查询会返回错误的结果。

您的计算

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-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) @CurrDate移至BirthDate

的同一年

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

此范围为“主要”以及前一年和下一年创建三次。

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

答案 2 :(得分:0)

我已经简化了一点。我已经注释了进行计算的代码,所以回顾未来你会知道它在做什么(通常是一个救世主):)。

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.

答案 3 :(得分:0)

您可以尝试使用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