Check a date (excluding year) - sql

In SQL Server, how can I check if one calendar date consisting of a day and month is older than another certain date, programmatically?
For example: I need to check if TransactionDate is on or before June 30, in all year.
TransactionDate <= (June 30)

Use DATEPART like this:
declare #var1 date = '2016-02-07';
declare #var2 date = '2017-02-06';
SELECT CASE
WHEN DATEPART(MM, #var1 ) * 100 + DATEPART(DD, #var1 )
> DATEPART(MM, #var2 ) * 100 + DATEPART(DD, #var2 ) THEN 'YES'
ELSE 'NO' END AS LARGERDATE;
It compares the dates as two integers in form of MMDD. For example:
'2016-02-07' ==> 207, '2017-02-06' ==> 206
'2010-10-27' ==> 1027, '2017-07-29' ==> 729

Most correct way will be to use DATEPART function; especially because it is available from all versions of SQL server since 2008, Azure SQL Database, Azure SQL Data Warehouse and Parallel Data Warehouse too.
You can check using the expression assuming you have the date to be compared against stored in #yourCheckDate variable
DECLARE #yourCheckDate DATETIME
DECLARE #m INT
DECLARE #d INT
SELECT #yourCheckDate = CAST('2017-6-30 12:15:32' AS DATETIME)
SELECT #m= DATEPART(month, #yourCheckDate)
SELECT #d= DATEPART(day, #yourCheckDate)
-- expression
select 1 where
DATEPART(month,#tranDate) < #m
OR
( DATEPART(month,#tranDate) = #m AND DATEPART(day,#tranDate) <= #d )

A SQL Server 2008 solution which supports any calendar date, derived from #TheEsisia and #Sami answers
WHERE 100*MONTH(TransactionDate) + DAY(TransactionDate) <= 100*MONTH(#checkDate) + DAY(#checkDate)

This should work if you want to get all dates from a date to the end of the year. Basically constructing a 'xxxx-12-31' with the input date (example in Oracle).
BETWEEN yourDate AND TO_DATE(TO_CHAR(yourDate, 'YYYY') ||'12-31', 'YYYY-MM-DD')

Related

Compare the date if the columns (day, month and year) are stored separately in SQL Server

I have 3 columns Day, Month and Year of type INT that are totally separate. What I need is to pass a date (format: yyyy-mm-dd) into a WHERE clause to check if this following date is matched or not. What would be the best approach to handle this issue?
In 2012 it would be DateFromParts(Year,Month,Day), but you have tagged 2008 which means we have to fall back to the older tricks.
dateadd(mm, (#YourYearValue - 1900) * 12 + #YourMonthValue- 1 , #YourDayValue - 1)
Put your 3 ints into that (via columns from a join or parameters as appropriate) and you have a date returned you can work with.
SQL Fiddle : http://www.sqlfiddle.com/#!18/9eecb/19988
For SQL Server 2008
declare #Day int = 29, #Month int = 5, #Year int = 2018
select t.*
from [table] t
where t.[Date] = cast(cast(#Year as char(4))+ '-' + cast(#Month as char(2)) + '-' + cast(#Day as char(2)) as date)
Only for 2012 and later use DATEFROMPARTS:
where t.[Date] = DATEFROMPARTS(#Year, #Month, #Day)
Maybe this solution:
where cast(cast(#yyyy as varchar(4))+'-'+cast(#mm as varchar(2))+'-'+cast(#dd as
varchar(2)) as date) ...
and replace #yyyy,#mm,#dd with your fields
I would suggest the following, Instead of making a date using separated values we can take part from the complete date using SQL functions and compare with accordingly, which I think the best way of comparison
DECLARE #Day INT=29, #Month INT=05, #Year INT = 2018,
#Date DATE = '2018-05-29'
SELECT * FROM yourTable
WHERE YEAR(#Date) = #Year
AND MONTH(#Date) = #Month
AND DAY(#Date) = #Day

SQL query to find employee aniversary

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

Converting year month day to date in sql server

My input to the stored procedure is a string (e.g '2 years 3 months 4 days') which is a future date. How to convert this to a date by comparing with current date?
declare #S varchar(50)
set #S = '2 years 3 months 4 days'
select dateadd(day, D.D, dateadd(month, D.M, dateadd(year, D.Y, getdate()))) as TheDate
from (select replace(replace(replace(#S, ' years ', '.'), ' months ', '.'), ' days', '')) as T(S)
cross apply (
select cast(parsename(T.S, 1) as int),
cast(parsename(T.S, 2) as int),
cast(parsename(T.S, 3) as int)Y
) as D(D, M, Y)
SQL Fiddle
You can use below Query in SP
select dateadd(yy,2,dateadd(m,3,dateadd(d,4,GETDATE())))
^Year ^Month ^Days
Here is the SP
create procedure test1
(
#year INT,
#month INT,
#day INT
)
AS
BEGIN
select dateadd(yy,#year,dateadd(m,#month,dateadd(d,#day,GETDATE())))
END
Use DATEADD, for example (add one year, to the current data):
DECLARE #datetime2 datetime2 = getdate();
SELECT 'year', DATEADD(year,1,#datetime2)
...
So, you should add 2 years, 3 months and 4 days to the current date and then return it as normal date (here I returned future year). Read here for details.
Before of the stored procedure invocation you should split the string in a server side language like PHP:
$str = '2 years 3 months 4 days';
preg_match_all('!\d+!', $str, $data);
So $data[0]=2, $data[1]=3 and $data[2] = 4, and so you can invoke #Luv procedure:
create procedure test1 -- thanks to Luv
(
#year INT,
#month INT,
#day INT
)
AS
BEGIN
select dateadd(yy,#year,dateadd(m,#month,dateadd(d,#day,GETDATE())))
END
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Convert seconds to human readable time duration
you may be able to split & convert this formatting into something which is useable via builtin SQL-functions - but i'd recommend using at least a pre-processing scriptlanguage like PHP in order to format the time correctly, PHP "relative" formats may just be the thing, i recall the datetime-class being quite powerful ...
http://www.php.net/manual/en/datetime.construct.php
http://www.php.net/manual/en/datetime.formats.relative.php
http://www.php.net/manual/en/datetime.formats.compound.php

Working out a date from a single month number SQL

Got 2 parameters #yr and #period, #period is just the month number so July would equal 7 for example.
In my stored procedure table I've got a column called Date which is just a standard datetime field. I need a where clause to work out all dates greater than the current period minus 1 year so if #period = 7 and #yr = 2012 I want the where clause to return all dates greater than '01-07-2011' (UK date format) how can I achieve this with just the 2 numbers from #period and #yr.
WHERE <br>
Date >= '01-07-2011'
You could
Date >= dateadd(month, #period-1, dateadd(year, #yr-1900, 0))
where year(date)>year(getdate()-1) and month(date)>#period
If you want the expression sargable, convert it to datetime:
declare #year int = 2012
declare #month int = 7
select
...
where [Date] >= convert(datetime, convert(varchar(4), #year)
+ right('0' + convert (varchar(2), #month), 2)
+ '01')
After seeing Alex K.'s answer, you might even do this:
dateadd(month, #month - 1 + (#year-1900) * 12, 0)
For the best performance you should do something like this:
declare #yr int = 2012
declare #period int = 7
select ...
from ....
WHERE date >= dateadd(month, (#yr - 1901) * 12 + #period - 1, 0)
We can do it in may ways
try it
DECLARE #a VARCHAR(20),
#b VARCHAR(10),
#c varchar(4)
SET #b='may' /*pass your stored proc value */
SET #c='2011'
SET #a='01'+#b+#c
SET DATEFORMAT YDM
SELECT CAST(#a AS DATE)
FOR uk formate
SELECT CONVERT(char,CAST(#a AS DATE),103)
Just t make sure you compare against an entire date, one solution I'd offer is:
Select *
from TheTable
where date> DateAdd(Year,-1, convert(datetime, '01/'+convert(varchar,#period)+'/' + convert(varchar,#yr)))
To account for regional format differences in SQL Server 2012:
Select *
from TheTable
where date> DateAdd(Year,-1, DateFromParts(#year,#period,1))
For pre-2012:
Select *
from TheTable
Where Date > DateAdd(day, 0, DateAdd(month, #period-1, DateAdd(year, (#yr-1900)-1,0)))
The #yr-1900 is maintained to illustrate the computation of the base date offset from 1900, then subtracting 1 for the one-year-off date computation

How to get date difference between two dates in same year with one date is from an input date not from the year

Well this is my case: I have an input date X (dd-mm-yyyy), and I want to count the number of days between it with the year part is changed into current year and today's date in SQL. I t comes with the following condition, after the year is changed temporarily: (Here's my current idea of the logic)
- If date X is earlier than today, then difference = datediff(X,now), with the X year is current year
- If date X is later than today, then difference = datediff(X,now), with the X year is one year before
Sample case:
1st case: The input date is 6-6-1990. Today (automatically generated) is 22-8-2011. Then the difference will be = datediff(6-6-2011,22-08-2011)
2nd case: The input date is 10-10-1990. Today (automatically generated) is 22-8-2011. Then the difference will be = datediff(10-10-2010,22-08-2011)
Any idea how to do this in SQL (in SQL Server)? Or is there any other more simple alternatives for this problem? I'd also like this to be done in the query and not using a stored procedure or function
Sorry if there's already a similar question, I just don't know the exact keyword for this problem :( if there's a question like this previously, feel free to direct me there.
Thanks in advance
Here is the implementation (if I understood the logic you need correctly):
USE YourDbName
GO
CREATE FUNCTION YearPartDiff (#date datetime)
RETURNS int
AS
BEGIN
DECLARE #dateCurrentYear datetime
SET #dateCurrentYear = DATEADD(year, YEAR(GETDATE()) - YEAR(#date), #date)
DECLARE #result int
IF #dateCurrentYear < GETDATE()
SET #result = ABS(DATEDIFF(day, #dateCurrentYear, GETDATE()))
ELSE
SET #result = ABS(DATEDIFF(day, DATEADD(year, -1, #dateCurrentYear), GETDATE()))
RETURN(#result)
END
GO
And the example of usage:
USE YourDbName
GO
DECLARE #someDate datetime
SET #someDate = '2011-06-06'
SELECT dbo.YearPartDiff(#someDate) /*returns 77*/
SET #someDate = '2010-10-10'
SELECT dbo.YearPartDiff(#someDate) /*returns 316*/
Basically, #Andrei's solution, but in a single statement:
SELECT
DayDiff = DATEDIFF(
DAY,
DATEADD(YEAR, CASE WHEN LastOcc > GETDATE() THEN -1 ELSE 0 END, LastOcc),
GETDATE()
)
FROM (
SELECT LastOcc = DATEADD(YEAR, YEAR(GETDATE()) - YEAR(#InputDate), #InputDate)
) s
This seems to do the job
SELECT DATEDIFF(DAY, CONVERT(DATETIME, N'2011-06-06'), CONVERT(DATETIME, N'2011-08-22'))
So the basic syntax is
SELECT DATEDIFF(DAY, CONVERT(DATETIME, N'yyyy-mm-dd'), CONVERT(DATETIME, N'yyyy-mm-dd '))
Alternatively, you can use GETDATE() instead of the string for today's date
I have used "SELECT DATEDIFF( D, "+myDate+", GETDATE())" in my code, on SQL Server 2005. It works for me. The value myDate of course would be the DateTime input value.
you should try this query:
create table #T (inp_date datetime)
insert #T values ('06-06-1990')
insert #T values ('08-22-1990')
insert #T values ('10-10-1990')
--select * from #T
select inp_date, GETDATE(),
CASE
WHEN DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE()),inp_date) <= GETDATE()
THEN DATEDIFF(dd,DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE()),inp_date),GETDATE())
ELSE DATEDIFF(dd,DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE())-1,inp_date),GETDATE())
END
from #T