Reputation:
I need to find anniversary date and anniversary year of employees and send email in every 14 days.But I have a problem with last week of December when using the following query if start date and end date are in different years.
Select * from Resource
where (DATEPART(dayofyear,JoinDate)
BETWEEN DATEPART(dayofyear,GETDATE())
AND DATEPART(dayofyear,DateAdd(DAY,14,GETDATE())))
Upvotes: 5
Views: 6528
Reputation: 136164
Instead of comparing to a dayofyear
(which resets to zero at jan 1st and is the reason your query breaks within 14 days of the end of the year) you could update the employee's joindate
to be the current year for the purpose of the query and just compare to actual dates
Select * from Resource
-- Add the number of years difference between joinDate and the current year
where DATEADD(year,DATEDIFF(Year,joinDate,GetDate()),JoinDate)
-- compare to range "today"
BETWEEN GetDate()
-- to 14 days from today
AND DATEADD(Day,14,GetDate())
-- duplicate for following year
OR DATEADD(year,DATEDIFF(Year,joinDate,GetDate())+1,JoinDate) -- 2016-1-1
BETWEEN GetDate()
AND DATEADD(Day,14,GetDate())
Test query:
declare @joindate DATETIME='2012-1-1'
declare @today DATETIME = '2015-12-26'
SELECT @joinDate
where DATEADD(year,DATEDIFF(Year,@joinDate,@today),@JoinDate) -- 2015-1-1
BETWEEN @today -- 2015-12-26
AND DATEADD(Day,14,@today) -- 2016-01-09
OR DATEADD(year,DATEDIFF(Year,@joinDate,@today)+1,@JoinDate) -- 2016-1-1
BETWEEN @today -- 2015-12-26
AND DATEADD(Day,14,@today) -- 2016-01-09
(H/T @Damien_The_Unbeliever for a simple fix)
The above correctly selects the joinDate
which is in the first week of Jan (note I've had to fudge @today
as Ive not managed to invent time travel).
The above solution should also solve the issue with leap years that was hiding in your original solution.
Update
You expressed in comments the requirement to select AnniversaryDate
and Years
of service, you need to apply some CASE
logic to determine whether to add 1 (year or date) to your select
select *,
CASE
WHEN DATEADD(YEAR,DATEDIFF(Year,JoinDate,GETDATE()),JoinDate) < GetDate()
THEN DATEDIFF(Year,JoinDate,GETDATE())+1
ELSE DATEDIFF(Year,JoinDate,GETDATE())
END as [Years],
CASE WHEN DATEADD(YEAR,DATEDIFF(Year,JoinDate,GETDATE()),JoinDate) < GetDate()
THEN DATEADD(YEAR,DATEDIFF(Year,JoinDate,GETDATE())+1,JoinDate)
ELSE DATEADD(YEAR,DATEDIFF(Year,JoinDate,GETDATE()),JoinDate)
end as [AnniversaryDate]
.... // etc
Upvotes: 7
Reputation: 3844
Try this:
DECLARE @Today DATE = GETDATE() --'12/25/2013'
DECLARE @Duration INT = 14
;WITH Recur AS
(
SELECT @Today AS RecurDate
UNION ALL
SELECT DATEADD(DAY, 1, RecurDate)
FROM Recur
WHERE DATEDIFF(DAY, @Today, RecurDate)+1 < @Duration
)
SELECT
r.*
FROM
Resource r
JOIN Recur
ON CONVERT(VARCHAR(5), JoinDate, 101) = CONVERT(VARCHAR(5), RecurDate, 101)
WHERE JoinDate < @Today
Upvotes: 0
Reputation: 6622
You can use the SQL DATEADD() function with week number parameter Here is how you can use it:
DECLARE @date date = getdate()
Select * from Resource
where
JoinDate BETWEEN @date AND DATEADD(ww,2,@date)
Upvotes: -2
Reputation: 1491
You could do this:
Select * from Resource
where DATEPART(dayofyear,JoinDate)
BETWEEN DATEPART(dayofyear,GETDATE())
AND DATEPART(dayofyear,DateAdd(DAY,14,GETDATE()))
OR
DATEPART(dayofyear,JoinDate)
BETWEEN (DATEPART(dayofyear,GETDATE()) + 365)
AND (DATEPART(dayofyear,DateAdd(DAY,14,GETDATE())) + 365)
Upvotes: 0