SQL Server not showing correct week numbers for given date - tsql

SQL Server is showing week 53 for first week of 2011 except 1th of January, and needs to be week 1.
Below is the query and output:
declare #T table (dt datetime)
insert into #T values
('2010-12-26'),
('2010-12-27'),
('2010-12-28'),
('2010-12-29'),
('2010-12-30'),
('2010-12-31'),
('2011-01-01'),
('2011-01-02'),
('2011-01-03'),
('2011-01-04'),
('2011-01-05'),
('2011-01-06'),
('2011-01-07'),
('2011-01-08')
select dt,DATEPART(wk,dt) from #T
Output:
2010-12-26 00:00:00.000 53
2010-12-27 00:00:00.000 53
2010-12-28 00:00:00.000 53
2010-12-29 00:00:00.000 53
2010-12-30 00:00:00.000 53
2010-12-31 00:00:00.000 53
2011-01-01 00:00:00.000 1
2011-01-02 00:00:00.000 2
2011-01-03 00:00:00.000 2
2011-01-04 00:00:00.000 2
2011-01-05 00:00:00.000 2
2011-01-06 00:00:00.000 2
2011-01-07 00:00:00.000 2
2011-01-08 00:00:00.000 2
I want SQL Server to show week 1 from Dec 26th - Jan 1th. Does anybody know how to accomplish this?
Thanks and regards,
Aschwin.

It was alot harder than I first expected. I am comparing the end of last year to see if it is qualified to be part of the new year. If so i set the week as 1, otherwise i just use the normal week.
declare #T table (dt datetime)
insert into #T values
('2010-12-25'),
('2010-12-26'),
('2010-12-27'),
('2010-12-28'),
('2010-12-29'),
('2010-12-30'),
('2010-12-31'),
('2011-01-01'),
('2011-01-02'),
('2011-01-03'),
('2011-01-04'),
('2011-01-05'),
('2011-01-06'),
('2011-01-07'),
('2011-01-08'),
('2011-12-31'),
('2012-01-01')
select dt,
week = case when dt + 6 - datediff(day, -1, dt) % 7 = dateadd(year, datediff(year,-1, dt), 0)
then 1 else datepart(week, dt) end from #t
Proof:
https://data.stackexchange.com/stackoverflow/q/110527/

I am not sure it holds for all years (but it looks like it) but you could solve this using a CASE statement.
SELECT dt
, CASE WHEN DATEPART(wk, dt) <> 53
THEN DATEPART(wk, dt)
ELSE 1
END
FROM #T
The new ISO_WEEK datepart doesn't apply to your requested output.

I Created 2 functions to deal with this issue
1) to get First or last day of the week
2) to get the week number or year
function 1
CREATE FUNCTION [dbo].[fn_GetDayOf]
(
#Date datetime,
--#FirstDayOfWeek int = 7,
#Mode int =1
)
/*
Mode 1: First Day Of Week
Mode 2: Last Day Of Week
*/
RETURNS datetime
WITH EXECUTE AS CALLER
BEGIN
Declare #Return datetime
--SET DATEFIRST #FirstDayOfWeek
IF #Mode = 1
BEGIN
select #Return = dateadd(day,-(datepart(weekday,#date)-1),convert(date,#date))
END
ELSE IF #Mode = 2
BEGIN
select #Return = dateadd(SECOND,-1,convert(datetime,dateadd(day,(datepart(weekday,#date)),convert(date,#date))))
END
ELSE
BEGIN
SET #Return = #Date
END
--SET DATEFIRST 7
RETURN #Return
END
Function 2
CREATE FUNCTION [dbo].[fn_GetYearWeek]
(
#Date datetime,
--#FirstDayOfWeek int = 7,
#Mode int =1
)
/*
Mode 1 = Week Number
Mode 2 = Year
*/
RETURNS INT
BEGIN
declare #Return int
IF #Mode = 1
BEGIN
select #Return = case when datepart(week,[dbo].[fn_GetDayOf] (#Date,1)) <> datepart(week,[dbo].[fn_GetDayOf] (#Date,2)) then datepart(week,[dbo].[fn_GetDayOf] (#Date,1)) else datepart(week,[dbo].[fn_GetDayOf] (#Date,2)) end
END
ELSE IF #Mode = 2
BEGIN
select #Return = case when datepart(WEEK,[dbo].[fn_GetDayOf] (#Date,1)) <> datepart(week,[dbo].[fn_GetDayOf] (#Date,2)) then datepart(YEAR,[dbo].[fn_GetDayOf] (#Date,1)) else datepart(YEAR,[dbo].[fn_GetDayOf] (#Date,2)) end
END
ELSE
BEGIN
SET #Return = -1
END
Return #Return
END
Running Example
declare #T table (dt datetime)
insert into #T values
('2010-12-25'),
('2010-12-26'),
('2010-12-27'),
('2010-12-28'),
('2010-12-29'),
('2010-12-30'),
('2010-12-31'),
('2011-01-01'),
('2011-01-02'),
('2011-01-03'),
('2011-01-04'),
('2011-01-05'),
('2011-01-06'),
('2011-01-07'),
('2011-01-08'),
('2011-12-31'),
('2012-01-01'),
('2012-01-02'),
('2012-12-31'),
('2013-01-01')
select
dt,
datepart(week,dt),
--case when datepart(week,[dbo].[fn_GetDayOf] (dt,1)) <> datepart(week,[dbo].[fn_GetDayOf] (dt,2)) then datepart(week,[dbo].[fn_GetDayOf] (dt,1)) else datepart(week,[dbo].[fn_GetDayOf] (dt,2)) end
[dbo].[fn_GetYearWeek] (dt,1),
[dbo].[fn_GetYearWeek] (dt,2)
from #T
result:

Another way to retrieve the total number of weeks in current year:
DECLARE #LASTDAY DATETIME
DECLARE #weeks INT
SET #LASTDAY = DATEADD(ms,-3,DATEADD(yy,0,DATEADD(yy,DATEDIFF(yy,0,GETDATE())+1,0)))
SELECT #weeks = CASE DATEname(dw,#LASTDAY)
WHEN 'MONDAY' THEN DATEPART(WK, DATEADD(wk,DATEDIFF(wk,7,#LASTDAY),5))
WHEN 'TUESDAY' THEN DATEPART(WK, DATEADD(wk,DATEDIFF(wk,7,#LASTDAY),5))
WHEN 'WEDNESDAY' THEN DATEPART(WK, DATEADD(wk,DATEDIFF(wk,7,#LASTDAY),5))
ELSE DATEPART(WK, #LASTDAY)
END
select #weeks

Related

Find total number in a specific period of time SQL

I am trying to find the total number of members in a given period. Say I have the following data:
member_id start_date end_date
1 9/1/2013 12/31/2013
2 10/1/2013 11/12/2013
3 12/1/2013 12/31/2013
4 5/1/2012 8/5/2013
5 9/1/2013 12/31/2013
6 7/1/2013 12/31/2013
7 6/6/2012 12/5/2013
8 10/1/2013 12/31/2013
9 7/8/2013 12/31/2013
10 1/1/2012 11/5/2013
In SQL I need to create a report that will list out the number of members in each month of the year. In this case something like the following:
Date Members Per Month
Jan-12 1
Feb-12 1
Mar-12 1
Apr-12 1
May-12 2
Jun-12 3
Jul-12 3
Aug-12 3
Sep-12 3
Oct-12 3
Nov-12 3
Dec-12 3
Jan-13 3
Feb-13 3
Mar-13 3
Apr-13 3
May-13 3
Jun-13 3
Jul-13 5
Aug-13 4
Sep-13 6
Oct-13 8
Nov-13 6
Dec-13 6
So there is only 1 member from Jan-12 (member id 10) until May-12 when member id 4 joins making the count 2 and so on.
The date range can be all over so I can't specify the specific dates but it is by month, meaning that even if someone ends 12-1 it is considered active for the month for Dec.
I was able to create the following stored procedure that was able to accomplish what I needed:
USE [ValueBasedSandbox]
GO
/****** Object: StoredProcedure [dbo].[sp_member_count_per_month] Script Date: 01/08/2015 12:02:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Create date: 2015-08-01
-- Description: Find the counts per a given date passed in
-- =============================================
CREATE PROCEDURE [dbo].[sp_member_count_per_month]
-- Add the parameters for the stored procedure here
#YEAR int
, #ENDYEAR int
AS
DECLARE #FIRSTDAYMONTH DATETIME
DECLARE #LASTDAYMONTH DATETIME
DECLARE #MONTH INT = 1;
--Drop the temporary holding table if exists
IF OBJECT_ID('tempdb.dbo.##TEMPCOUNTERTABLE', 'U') IS NOT NULL
DROP TABLE dbo.##TEMPCOUNTERTABLE
CREATE TABLE dbo.##TEMPCOUNTERTABLE (
counter INT
, start_date DATETIME2
, end_date DATETIME2
)
--Perform this loop for each year desired
WHILE #YEAR <= #ENDYEAR
BEGIN
--Perform for each month of the year
WHILE (#MONTH <= 12)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET #FIRSTDAYMONTH = DATEADD(MONTH, #MONTH - 1, DATEADD(YEAR, #YEAR-1900, 0))
SET #LASTDAYMONTH = DATEADD(MONTH, #MONTH, DATEADD(YEAR, #YEAR-1900, 0)-1)
INSERT INTO dbo.##TEMPCOUNTERTABLE(counter, start_date, end_date)
SELECT COUNT(*) AS counter
, #FIRSTDAYMONTH AS start_date
, #LASTDAYMONTH AS end_date
FROM dbo.member_table
WHERE start_date <= #LASTDAYMONTH
AND end_date >= #FIRSTDAYMONTH
--Increment through all the months of the year
SET #MONTH = #MONTH + 1
END -- End Monthly Loop
--Reset Month counter
SET #MONTH = 1
--Increment the desired years
SET #YEAR = #YEAR + 1
END -- End Yearly Loop
--Display the results
SELECT *
FROM dbo.##TEMPCOUNTERTABLE
-- Drop the temp table
IF OBJECT_ID('tempdb.dbo.##TEMPCOUNTERTABLE', 'U') IS NOT NULL
DROP TABLE dbo.##TEMPCOUNTERTABLE
GO
This should do the trick
with datesCte(monthStart,monthEnd) as
(
select cast('20120101' as date) as monthStart, cast('20120131' as date) as monthEnd
union all
select DATEADD(MONTH, 1, d.monthStart), dateadd(day, -1, dateadd(month, 1, d.monthStart))
from datesCte as d
where d.monthStart < '20140101'
)
select *
from datesCte as d
cross apply
(
select count(*) as cnt
from dbo.MemberDates as m
where m.startDate <= d.monthEnd and m.endDate > d.monthStart
) as x
order by d.monthStart

Understanding TSQL Coalesce function

I am trying to select all 12 months / year. And I thought following TSQL code would do this. However, this does not include all months like I want. What is the cause of this? This is modified code:
DECLARE #END_YEAR VARCHAR(10)
DECLARE #END_MONTH VARCHAR(10)
SET #END_YEAR = '2010'
SET #END_MONTH = '10'
DECLARE #TheMonthLastDate DATETIME
DECLARE #TempDate DATETIME
SET #TempDate = '2010-11-01 00:00:00.000'
SET #TheMonthLastDate = '2010-11-01 00:00:00.000'
;with months
as
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, #TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where m > dateadd(month, -12, #TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE
(BTK_CLOSED_DATE < #TheMonthLastDate OR
TSK_START_DATE < #TheMonthLastDate
)
)
select yt.DateClosed 'r2', m.m 'r3',
month(coalesce(yt.DateClosed, m.m)) as 'MonthClosed',
year(coalesce(yt.DateClosed, m.m)) as 'YearClosed'
from months m
left join yourTable yt
on
( datepart(year, yt.DateClosed) = DATEPART(year, m.m)
and datepart(month, yt.DateClosed) = DATEPART(month, m.m)
or
datepart(year, yt.DateOpened) = DATEPART(year, m.m)
and datepart(month, yt.DateOpened) = DATEPART(month, m.m)
)
AND year(coalesce(yt.DateClosed, m.m)) = 2010
order by yt.DateClosed
So above query does not return all months. But if I change above WHERE lines to:
FROM [PROC].ALL_AUDIT
WHERE
BTK_CLOSED_DATE < #TheMonthLastDate
then this query does return all 12 months. How can this be?
Output that I want and that I see when WHERE is BTK_CLOSED_DATE < #TheMonthLastDate:
r2 r3 MonthClosed YearClosed
NULL 2010-06-01 00:00:00.000 6 2010
NULL 2009-11-01 00:00:00.000 11 2009
2010-01-06 20:02:19.127 2010-01-01 00:00:00.000 1 2010
2010-01-27 23:13:45.570 2010-01-01 00:00:00.000 1 2010
2010-02-15 14:49:14.427 2010-02-01 00:00:00.000 2 2010
2010-02-15 14:49:14.427 2009-12-01 00:00:00.000 2 2010
But if I instead use WHERE:
(BTK_CLOSED_DATE < #TheMonthLastDate OR
TSK_START_DATE < #TheMonthLastDate
)
then I see:
r2 r3 MonthClosed YearClosed
NULL 2010-10-01 00:00:00.000 10 2010
NULL 2010-09-01 00:00:00.000 9 2010
NULL 2010-09-01 00:00:00.000 9 2010
NULL 2010-08-01 00:00:00.000 8 2010
NULL 2010-08-01 00:00:00.000 8 2010
...
So notice that in first result I see NULL for June 2010, which is what I want.
I think the problem has something to do with the fact that my data contains 2009-2011 data, but I only compare months and not years. How would I add in this additional logic?
The only place where you are reducing the data is with the WHERE clause you have already identified. Therefore, the reason you are not getting all the months you expect is down to the column TSK_START_DATE not being less than #TheMonthLastDate for all months.
To prove this hypothesis, run the following section of your query (I have commented out part of the where clause and removed everything under 'yourTable' cte). The results should show you what is being returned in the TSK_Start_Date column for your missing months and help you identify why the rows are missing when applying the < #TheMonthLastDate clause.
DECLARE #END_YEAR VARCHAR(10)
DECLARE #END_MONTH VARCHAR(10)
SET #END_YEAR = '2010'
SET #END_MONTH = '10'
DECLARE #TheMonthLastDate DATETIME
DECLARE #TempDate DATETIME
SET #TempDate = '2010-11-01 00:00:00.000'
SET #TheMonthLastDate = '2010-11-01 00:00:00.000'
;with months
as
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, #TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where m > dateadd(month, -12, #TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE
(BTK_CLOSED_DATE < #TheMonthLastDate OR
--TSK_START_DATE < #TheMonthLastDate
)
)
select * , #TheMonthLastDate TheMonthLastDate from yourTable

Is it possible to set start of week for T-SQL DATEDIFF function?

I use DATEDIFF function to filter records added this week only:
DATEDIFF(week, DateCreated, GETDATE()) = 0
and I noticed what it's assumed what week starts on Sunday. But in my case I would prefer to set start of week on Monday. Is it possible somehow in T-SQL?
Thanks!
Update:
Below is an example showing what DATEDIFF doesn't check ##DATEFIRST variable so I need another solution.
SET DATEFIRST 1;
SELECT
DateCreated,
DATEDIFF(week, DateCreated, CAST('20090725' AS DATETIME)) AS D25,
DATEDIFF(week, DateCreated, CAST('20090726' AS DATETIME)) AS D26
FROM
(
SELECT CAST('20090724' AS DATETIME) AS DateCreated
UNION
SELECT CAST('20090725' AS DATETIME) AS DateCreated
) AS T
Output:
DateCreated D25 D26
----------------------- ----------- -----------
2009-07-24 00:00:00.000 0 1
2009-07-25 00:00:00.000 0 1
(2 row(s) affected)
26 Jul 2009 is Sunday, and I want DATEDIFF returns 0 in third column too.
Yes it possible
SET DATEFIRST 1; -- Monday
from http://msdn.microsoft.com/en-us/library/ms181598.aspx
It appears datediff doesn't respect the Datefirst, so make it do so run it like this
create table #testDates (id int identity(1,1), dateAdded datetime)
insert into #testDates values ('2009-07-09 15:41:39.510') -- thu
insert into #testDates values ('2009-07-06 15:41:39.510') -- mon
insert into #testDates values ('2009-07-05 15:41:39.510') -- sun
insert into #testDates values ('2009-07-04 15:41:39.510') -- sat
SET DATEFIRST 7 -- Sunday (Default
select * from #testdates where datediff(ww, DATEADD(dd,-##datefirst,dateadded), DATEADD(dd,-##datefirst,getdate())) = 0
SET DATEFIRST 1 -- Monday
select * from #testdates where datediff(ww, DATEADD(dd,-##datefirst,dateadded), DATEADD(dd,-##datefirst,getdate())) = 0
Stolen from
http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/8cc3493a-7ae5-4759-ab2a-e7683165320b
I have another solution.
This should be easier to understand, correct me if I am wrong
SET DATEFIRST 1
select DATEDIFF(week, 0, DATEADD(day, -##DATEFIRST, '2018-04-15 00:00:00.000'))
We subtract '-1' from date and Sunday will become Saturday (which is 7nth day of week)
and Mondфy(2) will first day of week
So if i'm getting this correctly,
the only thing we need to do is remove 1 day from both dates on our datediff as following :
DATEDIFF(week,dateadd(day,-1,cast(GETDATE() as date)),
dateadd(day,-1,cast([Date] as date))) as RollingWeek

Splitting time + duration into intervals in t-sql

Does anyone know of a simple method for solving this?
I have a table which consists of start times for events and the associated durations. I need to be able to split the event durations into thirty minute intervals. So for example if an event starts at 10:45:00 and the duration is 00:17:00 then the returned set should allocate 15 minutes to the 10:30:00 interval and 00:02:00 minutes to the 11:00:00 interval.
I'm sure I can figure out a clumsy approach but would like something a little simpler. This must come up quite often I'd imagine but Google is being unhelpful today.
Thanks,
Steve
You could create a lookup table with just the times (over 24 hours), and join to that table. You would need to rebase the date to that used in the lookup. Then perform a datediff on the upper and lower intervals to work out their durations. Each middle interval would be 30 minutes.
create table #interval_lookup (
from_date datetime,
to_date datetime
)
declare #time datetime
set #time = '00:00:00'
while #time < '2 Jan 1900'
begin
insert into #interval_lookup values (#time, dateadd(minute, 30, #time))
set #time = dateadd(minute, 30, #time)
end
declare #search_from datetime
declare #search_to datetime
set #search_from = '10:45:00'
set #search_to = dateadd(minute, 17, #search_from)
select
from_date as interval,
case
when from_date <= #search_from and
#search_from < to_date and
from_date <= #search_to and
#search_to < to_date
then datediff(minute, #search_from, #search_to)
when from_date <= #search_from and
#search_from < to_date
then datediff(minute, #search_from, to_date)
when from_date <= #search_to and
#search_to < to_date then
datediff(minute, from_date, #search_to)
else 30
end as duration
from
#interval_lookup
where
to_date > #search_from
and from_date <= #search_to
Create TVF that splits single event:
ALTER FUNCTION dbo.TVF_TimeRange_Split_To_Grid
(
#eventStartTime datetime
, #eventDurationMins float
, #intervalMins int
)
RETURNS #retTable table
(
intervalStartTime datetime
,intervalEndTime datetime
,eventDurationInIntervalMins float
)
AS
BEGIN
declare #eventMinuteOfDay int
set #eventMinuteOfDay = datepart(hour,#eventStartTime)*60+datepart(minute,#eventStartTime)
declare #intervalStartMinute int
set #intervalStartMinute = #eventMinuteOfDay - #eventMinuteOfDay % #intervalMins
declare #intervalStartTime datetime
set #intervalStartTime = dateadd(minute,#intervalStartMinute,cast(floor(cast(#eventStartTime as float)) as datetime))
declare #intervalEndTime datetime
set #intervalEndTime = dateadd(minute,#intervalMins,#intervalStartTime)
declare #eventDurationInIntervalMins float
while (#eventDurationMins>0)
begin
set #eventDurationInIntervalMins = cast(#intervalEndTime-#eventStartTime as float)*24*60
if #eventDurationMins<#eventDurationInIntervalMins
set #eventDurationInIntervalMins = #eventDurationMins
insert into #retTable
select #intervalStartTime,#intervalEndTime,#eventDurationInIntervalMins
set #eventDurationMins = #eventDurationMins - #eventDurationInIntervalMins
set #eventStartTime = #intervalEndTime
set #intervalStartTime = #intervalEndTime
set #intervalEndTime = dateadd(minute,#intervalMins,#intervalEndTime)
end
RETURN
END
GO
Test:
select getdate()
select * from dbo.TVF_TimeRange_Split_To_Grid(getdate(),23,30)
Test Result:
2008-10-31 11:28:12.377
intervalStartTime intervalEndTime eventDurationInIntervalMins
----------------------- ----------------------- ---------------------------
2008-10-31 11:00:00.000 2008-10-31 11:30:00.000 1,79372222222222
2008-10-31 11:30:00.000 2008-10-31 12:00:00.000 21,2062777777778
Sample usage:
select input.eventName, result.* from
(
select
'first' as eventName
,cast('2008-10-03 10:45' as datetime) as startTime
,17 as durationMins
union all
select
'second' as eventName
,cast('2008-10-05 11:00' as datetime) as startTime
,17 as durationMins
union all
select
'third' as eventName
,cast('2008-10-05 12:00' as datetime) as startTime
,100 as durationMins
) input
cross apply dbo.TVF_TimeRange_Split_To_Grid(input.startTime,input.durationMins,30) result
Sample usage result:
eventName intervalStartTime intervalEndTime eventDurationInIntervalMins
--------- ----------------------- ----------------------- ---------------------------
first 2008-10-03 10:30:00.000 2008-10-03 11:00:00.000 15
first 2008-10-03 11:00:00.000 2008-10-03 11:30:00.000 2
second 2008-10-05 11:00:00.000 2008-10-05 11:30:00.000 17
third 2008-10-05 12:00:00.000 2008-10-05 12:30:00.000 30
third 2008-10-05 12:30:00.000 2008-10-05 13:00:00.000 30
third 2008-10-05 13:00:00.000 2008-10-05 13:30:00.000 30
third 2008-10-05 13:30:00.000 2008-10-05 14:00:00.000 10
(7 row(s) affected)

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