Month difference between two dates in sql server - sql

Please refer the below examples and kindly let me know your ideas.
declare #EmployeeStartDate datetime='01-Sep-2013'
declare #EmployeeEndDate datetime='15-Nov-2013'
select DateDiff(mm,#EmployeeStartDate, DateAdd(mm, 1,#EmployeeEndDate))
Output = 3
expected output = 2.5
Since I have only 15 days in Nov, So I should get 0.5 for Nov

Try this
SELECT CASE WHEN DATEDIFF(d,'2013-09-01', '2013-11-15')>30 THEN DATEDIFF(d,'2013-09-01', '2013-11-15')/30.0 ELSE 0 END AS 'MonthDifference'
OR
SELECT DATEDIFF(DAY, '2013-09-01', '2013-11-15') / 30.436875E

DateDiff compares the values of the column you specify to work out the difference, it doesn't compare both dates and give you an exact difference. You've told it to compare the Month values, so thats all it's looking it.
http://technet.microsoft.com/en-us/library/ms189794.aspx
The Technet article details the return value of the DateDiff Function - note that it's only int.
If you want the value as an exact figure (or nearabouts), you should datediff the dates on days, then divide by 30. For neatness, I've also rounded to a single decimal place.
select Round(Convert(decimal, DateDiff(dd,#EmployeeStartDate, #EmployeeEndDate)) / 30, 1)

select CAST(DATEDIFF(MONTH, StartDate, EndDate) AS float) -
(DATEPART(dd,StartDate)*1.0 - 1.0) / DAY(EOMONTH(StartDate)) +
((DATEPART(dd,EndDate)*1.0 ) / DAY(EOMONTH(EndDate)))

Here you go:
declare #EmployeeStartDate datetime='01-Sep-2013'
declare #EmployeeEndDate datetime='15-Nov-2013'
;WITH cDayDiff AS
(
select DateDiff(dd,#EmployeeStartDate, DateAdd(dd, 1,#EmployeeEndDate)) as days
)
SELECT
CAST(days as float) / 30 as Months
FROM
cDayDiff
It has 76 days which equals to 2.5333
Output:
Months
============
2.53333333333333

As far as I can tell, none of the other answers take into account that not all months are exactly 30 days long.
This is what I came up with:
DECLARE #StartDate DATETIME = '07-Oct-2018'
DECLARE #EndDate DATETIME = '06-Nov-2018'
SELECT
DATEDIFF(m, #StartDate, #EndDate)
+ 1.0 * DAY(#EndDate) / DAY(EOMONTH(#EndDate))
- 1.0 * DAY(#StartDate) / DAY(EOMONTH(#StartDate))
-- 0.974193548388
The formula can be explained like this:
The difference in months as output by DATEDIFF(m, ..., ...)
Plus the day of the last date divided by the number of days in that month
Minus the day of the first date divided by the number of days in that month
Note that in this case the answer from Ren Yuzhi gives the result 1.006451612904. The 1.0 is necessary to make the division happen in floating point rather than integer.

declare #EmployeeStartDate datetime='013-09-01'
declare #EmployeeEndDate datetime='2013-11-15'
SELECT DATEDIFF(month, #EmployeeStartDate, #EmployeeEndDate)
Thanks for this.
https://www.w3schools.com/sql/func_sqlserver_datediff.asp

You can use Below to calculate the No Of Months between two Dates in MySQL,
PERIOD_DIFF(concat(year(Date1),LPAD(month(Date1),2,0)),concat(year(Date2),LPAD(month(Date2),2,0)))

Related

How to get the exact year difference in SQL

I need a simple way to find the exact year difference between two dates.
For example between 01.11.2013 and 30.10.2019. In this case, it should be 5 years because current date has not reached 01.11 yet. But if it is between 29.10.2013 and 30.10.2019 then it should be 6 years.
Let assume these are birthday and current days. It's similar.
I've tried to get the result with the following code:
select datediff(year,20131101,20191030)
It is giving me 6 instead of 5. The closest solution I've found is:
select datediff(day,20131101,20191030)/365
But as we know there could be 1 or 2 leap years in this period and the result is again not exactly what I expect. Neither when we divide with 365 nor 366.
It is not necessary using datediff. I wonder if there is some simple way to present it or some stored function to do this for which existing I did't know.
You can take the year difference and then subtract 1 if necessary:
select (datediff(year, val1, val2) -
(case when month(val1) < month(val2) then 0
when month(val1) > month(val2) then 1
when day(val1) <= day(val2) then 0
else 1
end)
) as diff_years
You can try datediff Month / 12.
Declare #date1 Datetime
Declare #date2 Datetime
set #date1='2013-11-01 23:59:59'
set #date2='2019-10-30 00:00:00'
(select (datediff(HOUR, #date1, #date2)/24/365 ) as diff_years)

SQL 'Round' Up a Date to a Given Day of the week

My company groups all tasks into individual weeks that end on a Thursday. Thus a task due on 3/20/19 would be grouped into the 3/21 week and tasks due on 3/22 group into the 3/28/19 week.
I'm looking to calculate this field (called duedate_Weekdue) based on an input duedate.
The following works but doesn't seem like the simplest way to do this. Anyone have more elegant methods?
Select
getdate() as duedate,
datepart(yy,getdate()) as duedate_yr,
datepart(ww,getdate()) as duedate_ww,
CASE
When datename(dw,Dateadd(day,1,getdate()))='Thursday' Then Dateadd(day,1,getdate())
When datename(dw,Dateadd(day,2,getdate()))='Thursday' Then Dateadd(day,2,getdate())
When datename(dw,Dateadd(day,3,getdate()))='Thursday' Then Dateadd(day,3,getdate())
When datename(dw,Dateadd(day,4,getdate()))='Thursday' Then Dateadd(day,4,getdate())
When datename(dw,Dateadd(day,5,getdate()))='Thursday' Then Dateadd(day,5,getdate())
When datename(dw,Dateadd(day,6,getdate()))='Thursday' Then Dateadd(day,6,getdate())
When datename(dw,Dateadd(day,0,getdate()))='Thursday' Then Dateadd(day,0,getdate())
END as duedate_Weekdue;
You can reduce that to one line of code that uses a little math, and some SQL Engine trivia.
The answers that depend on DATEPART return non-deterministic results, depending on the setting for DATEFIRST, which tells the SQL Engine what day of the week to treat as the first day of the week.
There's a way to do what you want without the risk of getting the wrong result based on a change to the DATEFIRST setting.
Inside SQL Server, day number 0 is January 1, 1900, which happens to have been a Monday. We've all used this little trick to strip the time off of GETDATE() by calculating the number of days since day 0 then adding that number to day 0 to get today's date at midnight:
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()),0)
Similarly, day number 3 was January 4, 1900. That's relevant because that day was a Thursday. Applying a little math to the number of days, and relying on the DATEDIFF function to drop fractions, which it does, this calculation will always return the next Thursday for you:
SELECT DATEADD(DAY, (DATEDIFF(DAY, 3, GETDATE())/7)*7 + 7,3);
Credit to this answer for the assist.
So your final query comes down to this:
Select
getdate() as duedate,
datepart(yy,getdate()) as duedate_yr,
datepart(ww,getdate()) as duedate_ww,
DATEADD(DAY, (DATEDIFF(DAY, 3, GETDATE())/7)*7 + 7,3) as duedate_Weekdue;
If the first day of the week is Sunday, by using the modulo operator %:
cast(dateadd(day, (13 - datepart(dw, getdate())) % 7, getdate()) as date) as duedate_Weekdue
I also applied the casting of the result to date.
Try identifying number of day in week with DATEPART and then adding enough days to go to next thursday:
declare #dt date = '2019-03-22'
declare #weekDay int
SELECT #weekDay = DATEPART(dw, #dt)
if #weekDay <= 5
select DATEADD(day, 5 - #weekDay ,#dt)
else
select DATEADD(day, 12 - #weekDay ,#dt)

Get the actual month difference between two date

I working with strange queries in SQL, I want to find the actual month difference between two dates, for example
StartDate = '1-1-2013'
EndDate = '4-30-2013'
Here I want result to be 4 not 3
select datediff(mm, '1-1-2013', '4-30-2013')
This query will provide me result 3 but actual result is 4. Can anyone help me on this?
Not quite sure if this helps but here's my stab at it:
declare
#date1 datetime = '2013-01-01',
#date2 datetime = '2013-04-30'
select Cast(Round(Cast(DATEDIFF(DD,#date1, #date2) as decimal(5,2)) / 30, 1) as int) as Months
What you're asking isn't as simple as it first appears. One obvious way would be to add one day to your end date before doing the datediff. This would then be doing 1 Jan to 1 May which would be reported as four months.
However you need to consider if there's any tolerances; for example, should 1 Jan to 29 Apr be considered four months, or is that still three months? Obviously this will depend heavily on the context in which you are using these dates.
Please try to add 01-01-2013 and 04-30-2013 instead of what you added here
So query will be as below
select datediff(mm, '1-1-2013', '4-30-2013')
Thanks
Vasanthan
As others have pointed out, the result is absolutely correct: 3 months and 29 days.
You can of course check if the date in the end date is the last date of the month and make an adjustment to produce the desired result:
DECLARE #START DATETIME, #END DATETIME
SELECT #START = '2014-01-01', #END = '2014-04-30'
SELECT #START, #END
SELECT DATEDIFF(MONTH, #START, CASE WHEN MONTH(DATEADD(DAY, 1, #END)) > MONTH(#END) THEN DATEADD(DAY, +1, #END) ELSE #END END)
Not sure about the performance of said example (you're free to experiment with similar ideas), but what it does is add the last missing day to produce the 4 month difference whenever the end date represents the last day of that month.
Now, I agree with the others here that this is a weird thing to do, but if this is what your case requires, then so be it. We can't really comment on your business / programming specific needs here. :)

What is happening in this query?

I am trying to get the last of month, and in order to that i have written the following, to calculate the no. of days between today and the last date.
select datediff(DAY,GETDATE(),dateadd(m,1,getdate()))-GETDATE()
the bold part gives me the no. of days between today and a month from today, say 30 or 31. and then I am subtracting today's date from 30 or 31, which is " -getdate() "
The output for the above query is
1786-06-06 11:44:30.540
Could you please explain what is happening in the query? I am not looking for a solution, I would like to know how is SQL-Server interpreting the query.
Thanks. :)
The bold part of the expressions does not return a date, it returns a number of days:
31
Convert that to a datetime:
SELECT CONVERT(DATETIME, 31);
This is 31 days after day 0 (1900-01-01):
1900-02-01
Now, subtract GETDATE() as an integer (41512 days after day 0):
SELECT 31 - 41512 = -41481
Now add -41481 days to day 0:
SELECT DATEADD(DAY, -41481, 0);
-- or
SELECT DATEADD(DAY, -41481, '19000101');
Or:
SELECT CONVERT(DATETIME, 31 - CONVERT(INT, GETDATE()));
Now, I strongly recommend a couple of things:
Don't use implicit date math. #date_var_or_col - 1 for example fails with new data types like DATE and DATETIME2.
Don't use shorthand like m. If you mean MONTH, just take the massive productivity hit and type out MONTH. To see why, tell me if this provides the results you expect:
SELECT DATEPART(y, GETDATE()), DATEPART(w, GETDATE());
I am subtracting today's date from 30 or 31, which is " -getdate() "
Sounds like you understand exactly what is happening, but maybe don't understand the results.
You are implicitly converting GETDATE() to a number, which represents the number of days (and fractional days) since 1/1/1900 12:00:00 AM
When you "subtract" GETDATE() (41,511 as of 8/27/2013) from 30 or 31 you get an answer of -41,480, or 41,480 days before 1/1/1900, which would be about 6/6/1786 (plus or minus a few hours for the fractional part).

SQL Date Diff disregarding Year

i want to make a select, where the users birthday(date field) is less than 30 days.
what is the best way to to do it? i tried datediff, but i don't know how to put the year aside.
Thanks
You could just use DATEPART function with dayofyear datepart value.
EDIT: honestly, there is a boundary issue in my previous answer (many thanks to Damien): e.g. 2010-12-25 and 2011-01-07 => the difference should be less then 30 days, but DATEPART(dayofyear, #date) - DATEPART(dayofyear, [Birthday]) < 30 condition would skip this record. So I added an additional contition to my answer:
DATEPART(dy, #d) - DATEPART(dy, [Birthday]) < 30 OR
(
DATEPART(mm, #d) = 12 AND
DATEPART(dy, DATEADD(m, 1, #d)) - DATEPART(dy, DATEADD(m, 1, [Birthday])) < 30
)
it adds one month to the each date in the case when the month part of the first date is December and compares the difference.
A common way is to compose a formatted date, as text, and replace the year with the current year; and parse back into a date. Apply datediff on that.
If you find out datediff returns something negative thus the birthday of this year is in the past, add 1 year, and try again. This is for the time period around New Year.
SELECT *
FROM dbo.CheckBirthDay
WHERE (CASE WHEN YEAR(BirthDay) <= YEAR(CURRENT_TIMESTAMP) THEN DATEDIFF(DD,BirthDay,CURRENT_TIMESTAMP) END < 30 )