Get difference between two dates in Years - sql-server-2008-r2

I am working with a table that has StartDate and EndDate fields. I need to find difference between then in years.
Example:
StartDate = 1/1/2017
EndDate = 12/31/2017
I expect Result = 1 for the date difference.
Also, I'd like to round it to nearest whole number.
Example:
StartDate = 1/1/2017
EndDate = 11/30/2017
I expect Result = 1 for the date difference.
Using datediff function, I am able to get the result, but it isn't rounding to nearest whole number.
Example query:
I am getting 6 years even though 65 months / 12 would be less than 5.5:
select (DATEDIFF(yy, '01/01/2016', '5/31/2021')
+ CASE WHEN abs(DATEPART(day, '01/01/2016') - DATEPART(day, '05/31/2021')) > 15 THEN 1 ELSE 0 END)
select (DATEDIFF(mm, '01/01/2016', '05/31/2021')
+ CASE WHEN abs(DATEPART(day, '01/01/2016') - DATEPART(day, '05/31/2021')) > 15 THEN 1 ELSE 0 END)

DECLARE #startdate DATETIME = '1-1-2017',
#enddate DATETIME = '12-31-2018'
SELECT #startdate as StartDate, #enddate as EndDate,
DATEDIFF(YEAR, #startdate, #enddate)
-
(CASE
WHEN DATEADD(YEAR,
DATEDIFF(YEAR, #startdate,#enddate), #startdate)
> #enddate THEN 1
ELSE 0 END) 'Date difference in Years'
Use this code, I hope it will help you.

So far following query seems to be working okay. My mistake was I dividing by 12 instead of 12.0 for rounding to work correctly. Who knew! :
select
Round((DATEDIFF(mm, '01/01/2016', '07/1/2017')
+ CASE WHEN abs(DATEPART(day, '01/01/2016') - DATEPART(day, '06/30/2017')) > 15 THEN 1 ELSE 0 END) / 12.0, 0)

This may be a bit old but when using Oracle SQL Developer you can use the following. Just add your Dates below. I was using DateTime. This was used to get years between 0 and 10.
TRUNC((MONTHS_BETWEEN(<DATE_ONE>, <DATE_TWO>) * 31) / 365) > 0 and TRUNC((MONTHS_BETWEEN(<DATE_ONE>, <DATE_TWO>) * 31) / 365) < 10

Related

How do I use a calculated value within a DATEFROMPARTS in SQL

I need a calculated month value within DATEFROMPARTS function. The month has to be seven month prior to CURRENT_TIMESTAMP month.
This is what I tried:
DATEFROMPARTS(Year(CURRENT_TIMESTAMP), Month(CURRENT_TIMESTAMP)-7, 1) as SevenMoAgo;
I will eventually use this in the following expression where '12-01-2018' is:
where RECORDED_SERVICE_STARTTIME > ='12-01-2018'
I later used
declare #CurMo AS INT;
declare #MonPri7 AS INT;
set #CurMo = Month(CURRENT_TIMESTAMP);
set #MonPri7 = (#CurMo -7);
Datefromparts(Year(CURRENT_TIMESTAMP), #MonPri7, 1) as SevenMoAgo;
This also did not work.
I get the following error message:
"Cannot construct data type date, some of the arguments have values which are not valid."
For the second code I get:
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'Datefromparts'.
Try this...
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 7, 0)
Let me explain. First off, we need to understand that SQL Server interprets 0 as 1900-01-01 as shown by the following DATEPART functions.
SELECT DATEPART(YEAR, 0) AS Year
, DATEPART(MONTH, 0) AS Month
, DATEPART(DAY, 0) AS Day;
Which returns...
Year Month Day
----------- ----------- -----------
1900 1 1
Therefore, my SQL could be rewritten as...
SELECT DATEADD(MONTH, DATEDIFF(MONTH, '1900-01-01', CURRENT_TIMESTAMP) - 7, '1900-01-01')
Now perhaps it is a little easier to see what is going on here. The DATEDIFF function returns the number number of months between 1900-01-01 and today (CURRENT_TIMESTAMP) which is 1434.
SELECT DATEADD(MONTH, 1434 - 7, '1900-01-01')
Then we subtract 7 from 1434 which is 1427 and add that many months back to 1900-01-01.
SELECT DATEADD(MONTH, 1427, '1900-01-01')
Which yields 2018-12-01.
The reason is #MonPri7 is equal to ZERO when you say (#CurMo -7)
There are many different ways to calculate it, but if you want to fix your logic, you should use this:
declare #CurMo AS INT;
declare #MonPri7 AS INT;
set #CurMo = Month(CURRENT_TIMESTAMP);
set #MonPri7 = (#CurMo -7);
declare #Y int = Year(CURRENT_TIMESTAMP) -- <-- This is new variable
-- if 7 months ago is ZERO then you should go back to prev year December
if #MonPri7 = 0
begin
set #MonPri7 = 12
set #Y = #Y - 1
end
Edit:
declare #SevenMonthsAgo datetime;
select #SevenMonthsAgo = Datefromparts(#Y, #MonPri7, 1);
SELECT yourfields
FROM yourtable
where RECORDED_SERVICE_STARTTIME > = '01-01-2019' and
RECORDED_SERVICE_STARTTIME > = #SevenMonthsAgo

Calculate month difference based on dates SQL Server 2008 R2

I would like to calculate the difference between two dates in months.
The problem:
SELECT DATEDIFF(mm, '2015-11-01', '2015-11-30')
The date difference returns 0. I want to display 1 instead. If the difference is more than 15 days then it should round to next month.
I tried using round and ceiling functions and division by 30, but it still doesn't give me the desired result.
Reason this question is different from "possible duplicate" is because I am looking for only month calculation based on Start and End date. Also, my Start and End date structure is beginning of a month and end of a month instead of exact dates.
Try this:
SELECT DATEDIFF(mm, '2015-11-01', '2015-11-30')
+ CASE WHEN (DATEDIFF(mm, '2015-11-01', '2015-11-30') = 0 and DATEDIFF(dd, '2015-11-01', '2015-11-30') > 15) THEN 1 ELSE 0 END CASE
Try this.
Select
DATEDIFF(mm, '2015-11-01', '2015-11-30')
+ CASE WHEN abs(DATEPART(day, '2015-11-01') - DATEPART(day, '2015-11-30')) > 15 THEN 1 ELSE 0 END

Select all rows 7 days prior from a specific date

I want to get all rows 7 days prior from 01/09/2017
I know I can do
Load_DTM <= '2017-01-09' and Load_DTM >= '2017-01-02'
But can I not use DateAdd or DatePart?
i.e. DateAdd(dd, -7, '2017-01-09')
Load_DTM BETWEEN DATEADD(dd,-7,'2017-01-09') AND '2017-01-09 11:59:59'
ought to work.
You should be able to do exactly what you showed in your example:
SELECT * FROM Table WHERE DateField = DATEADD(DAY, -7, '2017-09-01')
Since running:
SELECT DATEADD(DAY, -1, GETDATE())
Gives you:
2017-03-15 19:26:29.833

Calculate working days - Monday to Fri in Tsql

How can i calculate the last working five days which is monday to Friday. my current script gets the last monday's date, but i cannot get the last friday's date. Please help
declare #StartDate datetime
declare #EndDate datetime
--Calculate date range for report
select #EndDate = Cast(convert(char(10), getdate(), 101)+' 00:00:00' as datetime)
select #StartDate = DateAdd(d, -7, #EndDate)
select #EndDate = Cast(convert(char(10), getdate(), 101)+' 23:59:59' as datetime)
select #StartDate startdate
select #EndDate enddate
Datepart offers you an easy way to get the week day:
SET DATEFIRST 1 -- monday is first day of the week
SELECT DATEPART(weekday, '20110725')
-- result is 1
See T-SQL Date functions and SET DATEFIRST for more information.
Using the weekday, you can work out how many days ago last monday and friday are and use 'AddDate' (like you are doing now) to calculate those.
Note that you should really use DATEDIFF for this type of date range selection. If you select everything up to 23:59:59 there's always a chance that some records are left out. For example 23:59:59.001 is out of range but it's still on the same day. With DATEDIFF you can test whether it's on the same day, discarding the time part. No need to bother with casting to string, adding time and casting back.
The answer is more complex than people are assuming. What you need is to go 5 days back and find the first monday before that, and the first friday after that. You can eather use ##datefirst, a calculation or 'set firstdate 1' for that. I prefer not using the last one, because it can't be done in functions. As you can see i used the calculation, ##datefirst is just as good.
Assuming you want the last group of monday to friday that is in the past. This query will get that. If you trust your current monday, you can just add 5 days and subtract 1 minute (I wouldn't trust it, it only returns last monday if you run the query on a monday).
In my sql, I am not aiming for simplicity, I am aiming for effectivity.
DECLARE #getdate datetime = dateadd(day, cast(getdate() as int), 0)
-- the 'Declare' can also be written like this thanks to #Andriy M
--DECLARE #getdate = CAST(GETDATE() - 0.5 AS int)
SELECT #getdate - 5 - CAST(#getdate- 5 as int) % 7 monday,
dateadd(minute, -1, #getdate) - CAST(#getdate- 5 as int) % 7 friday
Result:
Monday Friday
2011-07-18 0:00:00 2011-07-22 23:59:00
*first solution was a day off #AndriyM pointed it out, it has been solved.
Answer to #Andriy M
For some reason it acted different than I expected. I can't explain it but try this
select cast(dateadd(day, cast(getdate() as int) - .5, 0) as datetime),
cast(dateadd(day, cast(getdate() as int), 0) as datetime),
cast(dateadd(day, cast(getdate() as int) + .5, 0) as datetime)
in the morning the last 2 fields has same value, in the evening the first 2 fields has the same value. I am as surprised as you are, I wish I could explain it. It was tested here
https://data.stackexchange.com/stackoverflow/query/new
These two questions:
Find last sunday
How to get last day of last week in sql?
might be of some help.
Although, if you already know how to find the last Monday, you can easily find the corresponding Friday by adding 4 days to the Monday date using the DATEADD() function. For example:
SELECT #EndDate = DATEADD(DAY, 4, #StartDate)
It's all relative to TODAY's date, right?
So find out what today is DATEPART(weekday, getdate())
And then turn that into an adjustment variable -- e.g.:
declare #adjustment int
set #adjustment = CASE DATEPART(weekday, getdate()) WHEN 'MONDAY' THEN 0 WHEN 'TUESDAY' THEN 1, ...END
So then the Monday you want would be today - 7 - #adjustment
...and the Friday you want would be Monday + 5
Declare #myMonday smalldatetime,
#myFriday smalldatetime
set #myMonday = getdate() - 7 - #adjustment
set #myFriday = #myMonday + 5
DECLARE #my int
DECLARE #myDeduct int
DECLARE #day INT
DECLARE #mydate DATETIME
SET #mydate = '2012-08-01'
SET #myDeduct = 0
SET DateFirst 1 -- Set it monday=1 (value)
--Saturday and Sunday on the first and last day of a month will Deduct 1
IF (DATEPART(weekday,(DATEADD(dd,-(DAY(#mydate)-1),#mydate))) > 5)
SET #myDeduct = #myDeduct + 1
IF (DATEPART(weekday,(DATEADD(dd,-(DAY(DATEADD(mm,1,#mydate))),DATEADD(mm,1,#mydate)))) > 5)
SET #myDeduct = #myDeduct + 1
SET #my = day(DATEADD(dd,-(DAY(DATEADD(mm,1,#mydate))),DATEADD(mm,1,#mydate)))
select (((#my/7) * 5 + (#my%7)) - #myDeduct) as Working_Day_per_month
I'll throw my hat in the ring too. :-)
DECLARE #Date datetime = '01/11/2015'
DECLARE #StartDate datetime = DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date - 6) % 7)), #Date - 6) -- MONDAY
DECLARE #EndDate datetime = DATEADD(d, (5 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date - 6) % 7)), #Date - 6) -- FRIDAY
SELECT '#Date' as Variable ,CONVERT(date, #Date) as DateValue ,DATENAME(dw, #Date) as DayOfTheWeek
UNION SELECT '#StartDate' as Variable ,CONVERT(date, #StartDate) as DateValue ,DATENAME(dw, #StartDate) as DayOfTheWeek
UNION SELECT '#EndDate' as Variable ,CONVERT(date, #EndDate) as DateValue ,DATENAME(dw, #EndDate) as DayOfTheWeek
-- Variable DateValue DayOfTheWeek
-- ---------- ---------- ------------
-- #Date 2015-01-11 Sunday
-- #StartDate 2015-01-05 Monday
-- #EndDate 2015-01-09 Friday
BONUS: Here you can generate a quick table of the 5 weekdays using the same technique.
SELECT DATENAME(dw, DATEADD(d, TT.DaysToAdd, DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date - 6) % 7)), #Date - 6))) as DayOfTheWeek
, DATEADD(d, TT.DaysToAdd, DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date - 6) % 7)), #Date - 6)) as DateValue
FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM (VALUES(0),(0),(0),(0),(0)) a(n)) as TT
-- DayOfTheWeek DateValue
-- ------------------------------ -----------------------
-- Monday 2015-01-05 00:00:00.000
-- Tuesday 2015-01-06 00:00:00.000
-- Wednesday 2015-01-07 00:00:00.000
-- Thursday 2015-01-08 00:00:00.000
-- Friday 2015-01-09 00:00:00.000
Here's an explanation:
1) First we need to know what date to begin our evaluation from. For this example, we chose to use Sunday, January 11th, 2015.
DECLARE #Date2 datetime = '01/11/2015'
1b) Here's a nice to have bonus technique of getting the name for the day of the week, given a date value
SELECT #Date2 as DateValue, DATENAME(dw, #Date2) as DayOfTheWeek
2) Next we need to know deterministically (based on the US calendar) what the given day of the week is numerically between 1 and 7
NOTE: 1899.12.31 is the first Sunday before 1900.01.01, which is the MINIMUM value for the SmallDateTime data type.
NOTE: Yes, you could use DATEPART(dw, #Date) like this more simply, but it is not deterministic given that certain server environments could have different configurations
RESULTS: 1 = Sunday | 2 = Monday | 3 = Tuesday | 4 = Wednesday | 5 = Thursday | 6 = Friday | 7 = Saturday
SELECT ((DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date2) % 7) + 1) [DayOfWeek Deterministic (Based on US)]
3) Now, given any date, you should have a deterministic way of determining the Monday for that given week
SELECT DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date2) % 7)), #Date2) as [Monday Day of the Week - Deterministic (Based on US)]
4) Now, given any date, you should have a deterministic way of determining the Friday for that given week
SELECT DATEADD(d, (5 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), #Date2) % 7)), #Date2) as [Monday Day of the Week - Deterministic (Based on US)]
5) The last date manipulation technique we need is to know how to get into a week that has the first full week of weekdays happening before it. For instance, if we are on a Sunday and we subtract 1 day from it, then we get to Saturday, which puts us in the previous week, which is the first full week of weekdays. Alternatively, if we also subtracted 1 day from Monday, it would only get us to Sunday, which is not the previous week, so subtracting 1 day is not enough. On the flip side, if we were on a Saturday and subtracted 7 days, it would take us past the previous full week of weekday, into the week before it, which is too far. Here's a run down of the analysis to figure out what the magic numbers is that you can subtract by that will work with any day of the week. As you can see below, the magic number is 6.
-- DAYS TO SUBTRACT
-- Day of the Week - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7
-- =============== ==== ==== ==== ==== ==== ==== ==== ====
-- Sunday Bad Good Good Good Good Good Good Good
-- Monday Bad Bad Good Good Good Good Good Good
-- Tuesday Bad Bad Bad Good Good Good Good Good
-- Wednesday Bad Bad Bad Bad Good Good Good Good
-- Thursday Bad Bad Bad Bad Bad Good Good Good
-- Friday Bad Bad Bad Bad Bad Bad Good Good
-- Saturday Good Good Good Good Good Good Good Bad
BONUS) If you want to have all the weekdays in little table, then you would want to also use a quick zero based "tally table". There are many ways to do this, so pick your flavor. Here are few.
SELECT * FROM (SELECT 0 as DaysToAdd UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) as TT
SELECT * FROM (SELECT TOP 5 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM sys.all_columns a CROSS JOIN sys.all_columns b) as TT
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM (VALUES(0),(0),(0),(0),(0)) a(n)) as TT

How to calculate age in T-SQL with years, months, and days

What would be the best way to calculate someone's age in years, months, and days in T-SQL (SQL Server 2000)?
The datediff function doesn't handle year boundaries well, plus getting the months and days separate will be a bear. I know I can do it on the client side relatively easily, but I'd like to have it done in my stored procedure.
Here is some T-SQL that gives you the number of years, months, and days since the day specified in #date. It takes into account the fact that DATEDIFF() computes the difference without considering what month or day it is (so the month diff between 8/31 and 9/1 is 1 month) and handles that with a case statement that decrements the result where appropriate.
DECLARE #date datetime, #tmpdate datetime, #years int, #months int, #days int
SELECT #date = '2/29/04'
SELECT #tmpdate = #date
SELECT #years = DATEDIFF(yy, #tmpdate, GETDATE()) - CASE WHEN (MONTH(#date) > MONTH(GETDATE())) OR (MONTH(#date) = MONTH(GETDATE()) AND DAY(#date) > DAY(GETDATE())) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(yy, #years, #tmpdate)
SELECT #months = DATEDIFF(m, #tmpdate, GETDATE()) - CASE WHEN DAY(#date) > DAY(GETDATE()) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(m, #months, #tmpdate)
SELECT #days = DATEDIFF(d, #tmpdate, GETDATE())
SELECT #years, #months, #days
Try this...
SELECT CASE WHEN
(DATEADD(year,DATEDIFF(year, #datestart ,#dateend) , #datestart) > #dateend)
THEN DATEDIFF(year, #datestart ,#dateend) -1
ELSE DATEDIFF(year, #datestart ,#dateend)
END
Basically the "DateDiff( year...", gives you the age the person will turn this year, so i have just add a case statement to say, if they have not had a birthday yet this year, then subtract 1 year, else return the value.
Simple way to get age as text is as below:
Select cast((DATEDIFF(m, date_of_birth, GETDATE())/12) as varchar) + ' Y & ' +
cast((DATEDIFF(m, date_of_birth, GETDATE())%12) as varchar) + ' M' as Age
Results Format will be:
**63 Y & 2 M**
Implemented by arithmetic with ISO formatted date.
declare #now date,#dob date, #now_i int,#dob_i int, #days_in_birth_month int
declare #years int, #months int, #days int
set #now = '2013-02-28'
set #dob = '2012-02-29' -- Date of Birth
set #now_i = convert(varchar(8),#now,112) -- iso formatted: 20130228
set #dob_i = convert(varchar(8),#dob,112) -- iso formatted: 20120229
set #years = ( #now_i - #dob_i)/10000
-- (20130228 - 20120229)/10000 = 0 years
set #months =(1200 + (month(#now)- month(#dob))*100 + day(#now) - day(#dob))/100 %12
-- (1200 + 0228 - 0229)/100 % 12 = 11 months
set #days_in_birth_month = day(dateadd(d,-1,left(convert(varchar(8),dateadd(m,1,#dob),112),6)+'01'))
set #days = (sign(day(#now) - day(#dob))+1)/2 * (day(#now) - day(#dob))
+ (sign(day(#dob) - day(#now))+1)/2 * (#days_in_birth_month - day(#dob) + day(#now))
-- ( (-1+1)/2*(28 - 29) + (1+1)/2*(29 - 29 + 28))
-- Explain: if the days of now is bigger than the days of birth, then diff the two days
-- else add the days of now and the distance from the date of birth to the end of the birth month
select #years,#months,#days -- 0, 11, 28
Test Cases
The approach of days is different from the accepted answer, the differences shown in the comments below:
dob now years months days
2012-02-29 2013-02-28 0 11 28 --Days will be 30 if calculated by the approach in accepted answer.
2012-02-29 2016-02-28 3 11 28 --Days will be 31 if calculated by the approach in accepted answer, since the day of birth will be changed to 28 from 29 after dateadd by years.
2012-02-29 2016-03-31 4 1 2
2012-01-30 2016-02-29 4 0 30
2012-01-30 2016-03-01 4 1 2 --Days will be 1 if calculated by the approach in accepted answer, since the day of birth will be changed to 30 from 29 after dateadd by years.
2011-12-30 2016-02-29 4 1 30
An short version of Days by case statement:
set #days = CASE WHEN day(#now) >= day(#dob) THEN day(#now) - day(#dob)
ELSE #days_in_birth_month - day(#dob) + day(#now) END
If you want the age of years and months only, it could be simpler
set #years = ( #now_i/100 - #dob_i/100)/100
set #months =(12 + month(#now) - month(#dob))%12
select #years,#months -- 1, 0
NOTE: A very useful link of SQL Server Date Formats
Here is a (slightly) simpler version:
CREATE PROCEDURE dbo.CalculateAge
#dayOfBirth datetime
AS
DECLARE #today datetime, #thisYearBirthDay datetime
DECLARE #years int, #months int, #days int
SELECT #today = GETDATE()
SELECT #thisYearBirthDay = DATEADD(year, DATEDIFF(year, #dayOfBirth, #today), #dayOfBirth)
SELECT #years = DATEDIFF(year, #dayOfBirth, #today) - (CASE WHEN #thisYearBirthDay > #today THEN 1 ELSE 0 END)
SELECT #months = MONTH(#today - #thisYearBirthDay) - 1
SELECT #days = DAY(#today - #thisYearBirthDay) - 1
SELECT #years, #months, #days
GO
The same sort of thing as a function.
create function [dbo].[Age](#dayOfBirth datetime, #today datetime)
RETURNS varchar(100)
AS
Begin
DECLARE #thisYearBirthDay datetime
DECLARE #years int, #months int, #days int
set #thisYearBirthDay = DATEADD(year, DATEDIFF(year, #dayOfBirth, #today), #dayOfBirth)
set #years = DATEDIFF(year, #dayOfBirth, #today) - (CASE WHEN #thisYearBirthDay > #today THEN 1 ELSE 0 END)
set #months = MONTH(#today - #thisYearBirthDay) - 1
set #days = DAY(#today - #thisYearBirthDay) - 1
return cast(#years as varchar(2)) + ' years,' + cast(#months as varchar(2)) + ' months,' + cast(#days as varchar(3)) + ' days'
end
create procedure getDatedifference
(
#startdate datetime,
#enddate datetime
)
as
begin
declare #monthToShow int
declare #dayToShow int
--set #startdate='01/21/1934'
--set #enddate=getdate()
if (DAY(#startdate) > DAY(#enddate))
begin
set #dayToShow=0
if (month(#startdate) > month(#enddate))
begin
set #monthToShow= (12-month(#startdate)+ month(#enddate)-1)
end
else if (month(#startdate) < month(#enddate))
begin
set #monthToShow= ((month(#enddate)-month(#startdate))-1)
end
else
begin
set #monthToShow= 11
end
-- set #monthToShow= convert(int, DATEDIFF(mm,0,DATEADD(dd,DATEDIFF(dd,0,#enddate)- DATEDIFF(dd,0,#startdate),0)))-((convert(int,FLOOR(DATEDIFF(day, #startdate, #enddate) / 365.25))*12))-1
if(#monthToShow<0)
begin
set #monthToShow=0
end
declare #amonthbefore integer
set #amonthbefore=Month(#enddate)-1
if(#amonthbefore=0)
begin
set #amonthbefore=12
end
if (#amonthbefore in(1,3,5,7,8,10,12))
begin
set #dayToShow=31-DAY(#startdate)+DAY(#enddate)
end
if (#amonthbefore=2)
begin
IF (YEAR( #enddate ) % 4 = 0 AND YEAR( #enddate ) % 100 != 0) OR YEAR( #enddate ) % 400 = 0
begin
set #dayToShow=29-DAY(#startdate)+DAY(#enddate)
end
else
begin
set #dayToShow=28-DAY(#startdate)+DAY(#enddate)
end
end
if (#amonthbefore in (4,6,9,11))
begin
set #dayToShow=30-DAY(#startdate)+DAY(#enddate)
end
end
else
begin
--set #monthToShow=convert(int, DATEDIFF(mm,0,DATEADD(dd,DATEDIFF(dd,0,#enddate)- DATEDIFF(dd,0,#startdate),0)))-((convert(int,FLOOR(DATEDIFF(day, #startdate, #enddate) / 365.25))*12))
if (month(#enddate)< month(#startdate))
begin
set #monthToShow=12+(month(#enddate)-month(#startdate))
end
else
begin
set #monthToShow= (month(#enddate)-month(#startdate))
end
set #dayToShow=DAY(#enddate)-DAY(#startdate)
end
SELECT
FLOOR(DATEDIFF(day, #startdate, #enddate) / 365.25) as [yearToShow],
#monthToShow as monthToShow ,#dayToShow as dayToShow ,
convert(varchar,FLOOR(DATEDIFF(day, #startdate, #enddate) / 365.25)) +' Year ' + convert(varchar,#monthToShow) +' months '+convert(varchar,#dayToShow)+' days ' as age
return
end
I use this Function I modified (the Days part) From #Dane answer: https://stackoverflow.com/a/57720/2097023
CREATE FUNCTION dbo.EdadAMD
(
#FECHA DATETIME
)
RETURNS NVARCHAR(10)
AS
BEGIN
DECLARE
#tmpdate DATETIME
, #years INT
, #months INT
, #days INT
, #EdadAMD NVARCHAR(10);
SELECT #tmpdate = #FECHA;
SELECT #years = DATEDIFF(yy, #tmpdate, GETDATE()) - CASE
WHEN (MONTH(#FECHA) > MONTH(GETDATE()))
OR (
MONTH(#FECHA) = MONTH(GETDATE())
AND DAY(#FECHA) > DAY(GETDATE())
) THEN
1
ELSE
0
END;
SELECT #tmpdate = DATEADD(yy, #years, #tmpdate);
SELECT #months = DATEDIFF(m, #tmpdate, GETDATE()) - CASE
WHEN DAY(#FECHA) > DAY(GETDATE()) THEN
1
ELSE
0
END;
SELECT #tmpdate = DATEADD(m, #months, #tmpdate);
IF MONTH(#FECHA) = MONTH(GETDATE())
AND DAY(#FECHA) > DAY(GETDATE())
SELECT #days =
DAY(EOMONTH(GETDATE(), -1)) - (DAY(#FECHA) - DAY(GETDATE()));
ELSE
SELECT #days = DATEDIFF(d, #tmpdate, GETDATE());
SELECT #EdadAMD = CONCAT(#years, 'a', #months, 'm', #days, 'd');
RETURN #EdadAMD;
END;
GO
It works pretty well.
I've seen the question several times with results outputting Years, Month, Days but never a numeric / decimal result. (At least not one that doesn't round incorrectly).
I welcome feedback on this function. Might not still need a little adjusting.
-- Input to the function is two dates.
-- Output is the numeric number of years between the two dates in Decimal(7,4) format.
-- Output is always always a possitive number.
-- NOTE:Output does not handle if difference is greater than 999.9999
-- Logic is based on three steps.
-- 1) Is the difference less than 1 year (0.5000, 0.3333, 0.6667, ect.)
-- 2) Is the difference exactly a whole number of years (1,2,3, ect.)
-- 3) (Else)...The difference is years and some number of days. (1.5000, 2.3333, 7.6667, ect.)
CREATE Function [dbo].[F_Get_Actual_Age](#pi_date1 datetime,#pi_date2 datetime)
RETURNS Numeric(7,4)
AS
BEGIN
Declare
#l_tmp_date DATETIME
,#l_days1 DECIMAL(9,6)
,#l_days2 DECIMAL(9,6)
,#l_result DECIMAL(10,6)
,#l_years DECIMAL(7,4)
--Check to make sure there is a date for both inputs
IF #pi_date1 IS NOT NULL and #pi_date2 IS NOT NULL
BEGIN
IF #pi_date1 > #pi_date2 --Make sure the "older" date is in #pi_date1
BEGIN
SET #l_tmp_date = #pi_date2
SET #pi_date2 = #Pi_date1
SET #pi_date1 = #l_tmp_date
END
--Check #1 If date1 + 1 year is greater than date2, difference must be less than 1 year
IF DATEADD(YYYY,1,#pi_date1) > #pi_date2
BEGIN
--How many days between the two dates (numerator)
SET #l_days1 = DATEDIFF(dd,#pi_date1, #pi_date2)
--subtract 1 year from date2 and calculate days bewteen it and date2
--This is to get the denominator and accounts for leap year (365 or 366 days)
SET #l_days2 = DATEDIFF(dd,dateadd(yyyy,-1,#pi_date2),#pi_date2)
SET #l_years = #l_days1 / #l_days2 -- Do the math
END
ELSE
--Check #2 Are the dates an exact number of years apart.
--Calculate years bewteen date1 and date2, then add the years to date1, compare dates to see if exactly the same.
IF DATEADD(YYYY,DATEDIFF(YYYY,#pi_date1,#pi_date2),#pi_date1) = #pi_date2
SET #l_years = DATEDIFF(YYYY,#pi_date1, #pi_date2) --AS Years, 'Exactly even Years' AS Msg
ELSE
BEGIN
--Check #3 The rest of the cases.
--Check if datediff, returning years, over or under states the years difference
SET #l_years = DATEDIFF(YYYY,#pi_date1, #pi_date2)
IF DATEADD(YYYY,#l_years,#pi_date1) > #pi_date2
SET #l_years = #l_years -1
--use basicly same logic as in check #1
SET #l_days1 = DATEDIFF(dd,DATEADD(YYYY,#l_years,#pi_date1), #pi_date2)
SET #l_days2 = DATEDIFF(dd,dateadd(yyyy,-1,#pi_date2),#pi_date2)
SET #l_years = #l_years + #l_days1 / #l_days2
--SELECT #l_years AS Years, 'Years Plus' AS Msg
END
END
ELSE
SET #l_years = 0 --If either date was null
RETURN #l_Years --Return the result as decimal(7,4)
END
`
Quite Old question, but I want to share what I have done to calculate age
Declare #BirthDate As DateTime
Set #BirthDate = '1994-11-02'
SELECT DATEDIFF(YEAR,#BirthDate,GETDATE()) - (CASE
WHEN MONTH(#BirthDate)> MONTH(GETDATE()) THEN 1
WHEN MONTH(#BirthDate)= MONTH(GETDATE()) AND DAY(#BirthDate) > DAY(GETDATE()) THEN 1
Else 0 END)
Are you trying to calculate the total days/months/years of an age? do you have a starting date? Or are you trying to dissect it (ex: 24 years, 1 month, 29 days)?
If you have a start date that you're working with, datediff will output the total days/months/years with the following commands:
Select DateDiff(d,'1984-07-12','2008-09-11')
Select DateDiff(m,'1984-07-12','2008-09-11')
Select DateDiff(yyyy,'1984-07-12','2008-09-11')
with the respective outputs being (8827/290/24).
Now, if you wanted to do the dissection method, you'd have to subtract the number of years in days (days - 365*years), and then do further math on that to get the months, etc.
Here is SQL code that gives you the number of years, months, and days since the sysdate.
Enter value for input_birth_date this format(dd_mon_yy). note: input same value(birth date) for years, months & days such as 01-mar-85
select trunc((sysdate -to_date('&input_birth_date_dd_mon_yy'))/365) years,
trunc(mod(( sysdate -to_date('&input_birth_date_dd_mon_yy'))/365,1)*12) months,
trunc((mod((mod((sysdate -to_date('&input_birth_date_dd_mon_yy'))/365,1)*12),1)*30)+1) days
from dual
DateTime values in T-SQL are stored as floats. You can just subtract the dates from each other and you now have a new date that is the timespan between them.
declare #birthdate datetime
set #birthdate = '6/15/1974'
--age in years - short version
print year(getdate() - #birthdate) - year(0)
--age in years - visualization
declare #mindate datetime
declare #span datetime
set #mindate = 0
set #span = getdate() - #birthdate
print #mindate
print #birthdate
print getdate()
print #span
--substract minyear from spanyear to get age in years
print year(#span) - year(#mindate)
print month(#span)
print day(#span)
CREATE FUNCTION DBO.GET_AGE
(
#DATE AS DATETIME
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #YEAR AS VARCHAR(50) = ''
DECLARE #MONTH AS VARCHAR(50) = ''
DECLARE #DAYS AS VARCHAR(50) = ''
DECLARE #RESULT AS VARCHAR(MAX) = ''
SET #YEAR = CONVERT(VARCHAR,(SELECT DATEDIFF(MONTH,CASE WHEN DAY(#DATE) > DAY(GETDATE()) THEN DATEADD(MONTH,1,#DATE) ELSE #DATE END,GETDATE()) / 12 ))
SET #MONTH = CONVERT(VARCHAR,(SELECT DATEDIFF(MONTH,CASE WHEN DAY(#DATE) > DAY(GETDATE()) THEN DATEADD(MONTH,1,#DATE) ELSE #DATE END,GETDATE()) % 12 ))
SET #DAYS = DATEDIFF(DD,DATEADD(MM,CONVERT(INT,CONVERT(INT,#YEAR)*12 + CONVERT(INT,#MONTH)),#DATE),GETDATE())
SET #RESULT = (RIGHT('00' + #YEAR, 2) + ' YEARS ' + RIGHT('00' + #MONTH, 2) + ' MONTHS ' + RIGHT('00' + #DAYS, 2) + ' DAYS')
RETURN #RESULT
END
SELECT DBO.GET_AGE('04/12/1986')
DECLARE #BirthDate datetime, #AgeInMonths int
SET #BirthDate = '10/5/1971'
SET #AgeInMonths -- Determine the age in "months old":
= DATEDIFF(MONTH, #BirthDate, GETDATE()) -- .Get the difference in months
- CASE WHEN DATEPART(DAY,GETDATE()) -- .If today was the 1st to 4th,
< DATEPART(DAY,#BirthDate) -- (or before the birth day of month)
THEN 1 ELSE 0 END -- ... don't count the month.
SELECT #AgeInMonths / 12 as AgeYrs -- Divide by 12 months to get the age in years
,#AgeInMonths % 12 as AgeXtraMonths -- Get the remainder of dividing by 12 months = extra months
,DATEDIFF(DAY -- For the extra days, find the difference between,
,DATEADD(MONTH, #AgeInMonths -- 1. Last Monthly Birthday
, #BirthDate) -- (if birthdays were celebrated monthly)
,GETDATE()) as AgeXtraDays -- 2. Today's date.
For the ones that want to create a calculated column in a table to store the age:
CASE WHEN DateOfBirth< DATEADD(YEAR, (DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, DateOfBirth))*-1, GETDATE())
THEN DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, DateOfBirth)
ELSE DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, DateOfBirth) -1 END
There is an easy way, based on the hours between the two days BUT with the end date truncated.
SELECT CAST(DATEDIFF(hour,Birthdate,CAST(GETDATE() as Date))/8766.0 as INT) AS Age FROM <YourTable>
This one has proven to be extremely accurate and reliable. If it weren't for the inner CAST on the GETDATE() it might flip the birthday a few hours before midnight but, with the CAST, it is dead on with the age changing over at exactly midnight.
Here is how I calculate the age given a birth date and the current date.
select case
when cast(getdate() as date) = cast(dateadd(year, (datediff(year, '1996-09-09', getdate())), '1996-09-09') as date)
then dateDiff(yyyy,'1996-09-09',dateadd(year, 0, getdate()))
else dateDiff(yyyy,'1996-09-09',dateadd(year, -1, getdate()))
end as MemberAge
go
There is another method for calculate age is
See below table
FirstName LastName DOB
sai krishnan 1991-11-04
Harish S A 1998-10-11
For finding age,you can calculate through month
Select datediff(MONTH,DOB,getdate())/12 as dates from [Organization].[Employee]
Result will be
firstname dates
sai 27
Harish 20
I have created a function calculateAge that takes parameter dateOfBirth from outside and then it calculates the age in years, months and days and finally it returns in string format.
CREATE FUNCTION calculateAge(dateOfBirth datetime) RETURNS varchar(40)
BEGIN
set #currentdatetime = CURRENT_TIMESTAMP;
set #years = TIMESTAMPDIFF(YEAR,dateOfBirth,#currentdatetime);
set #months = TIMESTAMPDIFF(MONTH,dateOfBirth,#currentdatetime) - #years*12 ;
set #dayOfBirth = EXTRACT(DAY FROM dateOfBirth);
set #today = EXTRACT(DAY FROM #currentdatetime);
set #days = 0;
if (#today > #dayOfBirth) then
set #days = #today - #dayOfBirth;
else
set #decreaseMonth = DATE_SUB(#currentdatetime, INTERVAL 1 MONTH);
set #days = DATEDIFF(dateOfBirth, #decreaseMonth);
end if;
RETURN concat(concat( concat(#years , "years\n") , concat(#months , "months\n")), concat(#days , "days"));
END
Plenty of solutions have been given already, but I beleive this one to be both easy to understand and reliable, as it will handle leap years as well :
case when datepart(dayofyear, #birth) <= datepart(dayofyear, getdate())
then datepart(year, getdate()) - datepart(year, #birth)
else datepart(year, getdate()) - datepart(year, #birth) - 1
end
The idea is to simply compute the difference in years between the two years (birth and now), and substract 1 if the anniversary has not been reached for the current year.
declare #StartDate datetime = '2016-01-31'
declare #EndDate datetime = '2016-02-01'
SELECT #StartDate AS [StartDate]
,#EndDate AS [EndDate]
,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END AS [Years]
,DATEDIFF(Month,(DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate)),#EndDate) - CASE WHEN DATEADD(Month, DATEDIFF(Month,DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate),#EndDate) , #StartDate) > #EndDate THEN 1 ELSE 0 END AS [Months]
,DATEDIFF(Day, DATEADD(Month,DATEDIFF(Month, (DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate)),#EndDate) - CASE WHEN DATEADD(Month, DATEDIFF(Month,DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate),#EndDate) , #StartDate) > #EndDate THEN 1 ELSE 0 END ,DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate)) ,#EndDate) - CASE WHEN DATEADD(Day,DATEDIFF(Day, DATEADD(Month,DATEDIFF(Month, (DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate)),#EndDate) - CASE WHEN DATEADD(Month, DATEDIFF(Month,DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate),#EndDate) , #StartDate) > #EndDate THEN 1 ELSE 0 END ,DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate)) ,#EndDate),DATEADD(Month,DATEDIFF(Month, (DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate)),#EndDate) - CASE WHEN DATEADD(Month, DATEDIFF(Month,DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate),#EndDate) , #StartDate) > #EndDate THEN 1 ELSE 0 END ,DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate) - CASE WHEN DATEADD(Year,DATEDIFF(Year,#StartDate,#EndDate), #StartDate) > #EndDate THEN 1 ELSE 0 END,#StartDate))) > #EndDate THEN 1 ELSE 0 END AS [Days]
select DOB as Birthdate,
YEAR(GETDATE()) as ThisYear,
YEAR(getdate()) - EAR(date1) as Age
from TableName
SELECT DOB AS Birthdate ,
YEAR(GETDATE()) AS ThisYear,
YEAR(getdate()) - YEAR(DOB) AS Age
FROM tableprincejain
DECLARE #DoB AS DATE = '1968-10-24'
DECLARE #cDate AS DATE = CAST('2000-10-23' AS DATE)
SELECT
--Get Year difference
DATEDIFF(YEAR,#DoB,#cDate) -
--Cases where year difference will be augmented
CASE
--If Date of Birth greater than date passed return 0
WHEN YEAR(#DoB) - YEAR(#cDate) >= 0 THEN DATEDIFF(YEAR,#DoB,#cDate)
--If date of birth month less than date passed subtract one year
WHEN MONTH(#DoB) - MONTH(#cDate) > 0 THEN 1
--If date of birth day less than date passed subtract one year
WHEN MONTH(#DoB) - MONTH(#cDate) = 0 AND DAY(#DoB) - DAY(#cDate) > 0 THEN 1
--All cases passed subtract zero
ELSE 0
END
declare #BirthDate datetime
declare #TotalYear int
declare #TotalMonths int
declare #TotalDays int
declare #TotalWeeks int
declare #TotalHours int
declare #TotalMinute int
declare #TotalSecond int
declare #CurrentDtTime datetime
set #BirthDate='1998/01/05 05:04:00' -- Set Your date here
set #TotalYear= FLOOR(DATEDIFF(DAY, #BirthDate, GETDATE()) / 365.25)
set #TotalMonths= FLOOR(DATEDIFF(DAY,DATEADD(year, #TotalYear,#BirthDate),GetDate()) / 30.436875E)
set #TotalDays= FLOOR(DATEDIFF(DAY, DATEADD(month, #TotalMonths,DATEADD(year,
#TotalYear,#BirthDate)), GETDATE()))
set #CurrentDtTime=CONVERT(datetime,CONVERT(varchar(50), DATEPART(year,
GetDate()))+'/' +CONVERT(varchar(50), DATEPART(MONTH, GetDate()))
+'/'+ CONVERT(varchar(50),DATEPART(DAY, GetDate()))+' '
+ CONVERT(varchar(50),DATEPART(HOUR, #BirthDate))+':'+
CONVERT(varchar(50),DATEPART(MINUTE, #BirthDate))+
':'+ CONVERT(varchar(50),DATEPART(Second, #BirthDate)))
set #TotalHours = DATEDIFF(hour, #CurrentDtTime, GETDATE())
if(#TotalHours < 0)
begin
set #TotalHours = DATEDIFF(hour,DATEADD(Day,-1, #CurrentDtTime), GETDATE())
set #TotalDays= #TotalDays -1
end
set #TotalMinute= DATEPART(MINUTE, GETDATE())-DATEPART(MINUTE, #BirthDate)
if(#TotalMinute < 0)
set #TotalMinute = DATEPART(MINUTE, DATEADD(hour,-1,GETDATE()))+(60-DATEPART(MINUTE,
#BirthDate))
set #TotalSecond= DATEPART(Second, GETDATE())-DATEPART(Second, #BirthDate)
Print 'Your age are'+ CHAR(13)
+ CONVERT(varchar(50), #TotalYear)+' Years, ' +
CONVERT(varchar(50),#TotalMonths) +' Months, ' +
CONVERT(varchar(50),#TotalDays)+' Days, ' +
CONVERT(varchar(50),#TotalHours)+' Hours, ' +
CONVERT(varchar(50),#TotalMinute)+' Minutes, ' +
CONVERT(varchar(50),#TotalSecond)+' Seconds. ' +char(13)+
'Your are born at day of week was - ' + CONVERT(varchar(50),DATENAME(dw ,
#BirthDate ))
+char(13)+char(13)+
+'Your Birthdate to till date your '+ CHAR(13)
+'Years - ' + CONVERT(varchar(50), FLOOR(DATEDIFF(DAY, #BirthDate, GETDATE()) /
365.25))
+' , Months - ' + CONVERT(varchar(50),DATEDIFF(MM,#BirthDate,getdate()))
+' , Weeks - ' + CONVERT(varchar(50),DATEDIFF(wk,#BirthDate,getdate()))
+' , Days - ' + CONVERT(varchar(50),DATEDIFF(dd,#BirthDate,getdate()))+char(13)+
+'Hours - ' + CONVERT(varchar(50),DATEDIFF(HH,#BirthDate,getdate()))
+' , Minutes - ' + CONVERT(varchar(50),DATEDIFF(mi,#BirthDate,getdate()))
+' , Seconds - ' + CONVERT(varchar(50),DATEDIFF(ss,#BirthDate,getdate()))
Output
Your age are
22 Years, 0 Months, 2 Days, 11 Hours, 30 Minutes, 16 Seconds.
Your are born at day of week was - Monday
Your Birthdate to till date your
Years - 22 , Months - 264 , Weeks - 1148 , Days - 8037
Hours - 192899 , Minutes - 11573970 , Seconds - 694438216