我是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);
为了获得正确的结果,我应该做些什么改变? 任何帮助将非常感谢! : - )
答案 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中对其进行了测试,因为它具有DATEADD
,GETDATE
函数。
当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-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
。
此范围为“主要”以及前一年和下一年创建三次。
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