如何用年,月,日计算T-SQL中的年龄

在T-SQL(SQL Server 2000)中,以年,月,日计算某人年龄的最佳方法是什么?

date的function不能很好地处理年份的边界,再加上把月份和date分开就是一个熊。 我知道我可以在客户端比较容易地做到这一点,但我希望在我的存储过程中完成 。

以下是一些T-SQL,它提供自@date中指定date以来的年数,月数和天数。 它考虑到了这样的事实,即DATEDIFF()计算差异而不考虑它是什么月份或date(所以8/31到9/1之间的月差是1个月),并用一个case语句来处理那个递减结果的地方适当。

 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 

尝试这个…

 SELECT CASE WHEN (DATEADD(year,DATEDIFF(year, @datestart ,@dateend) , @datestart) > @dateend) THEN DATEDIFF(year, @datestart ,@dateend) -1 ELSE DATEDIFF(year, @datestart ,@dateend) END 

基本上,“DateDiff(年…)”给了你今年会变的年龄,所以我刚刚添加一个案例说明,如果今年还没有过生日,那么减去1年,否则返回值。

简单的方法来获取文本的年龄如下:

 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 

结果格式将是:

 **63 Y & 2 M** 

这是一个(稍微)更简单的版本:

 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 

与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 

我已经多次看到这个问题,输出年,月,日的结果,但从来没有数字/十进制的结果。 (至less不是没有不正确的)。 我欢迎对这个function的反馈。 可能还不需要一点调整。

– 函数的input是两个date。 – 输出是Decimal(7,4)格式的两个date之间的数字。 – 输出始终是正数。

– 注:如果差值大于999.9999,则输出不处理

– 逻辑基于三个步骤。 – 1)差值小于1年(0.5000,0.33333,0.66667等) – 2)差值是否为整数年(1,2,3等)。

– 3)(其他)…区别是几年和几天。 (1.5000,2.33333,7.6667等)



 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 

`

相当古老的问题,但我想分享我所做的计算年龄

  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) 

通过带有ISO格式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 

testing用例

天的方法与接受的答案不同,下面的评论中显示了不同之处:

  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 

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 

如果你只想要几年和几个月的年龄,可能会更简单

 set @years = ( @now_i/100 - @dob_i/100)/100 set @months =(12 + month(@now) - month(@dob))%12 select @years,@months -- 1, 0 

注意: SQL Serverdate格式非常有用的链接

你想计算一个年龄的总天数/月/年? 你有开始date吗? 还是你想剖析它(例如:24年,1个月,29天)?

如果您有一个开始date,那么datediff会输出以下命令的总日/月/年:

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

各自的产出是(8827/290/24)。

现在,如果你想进行解剖的方法,你必须减去天数(天 – 365 *年)的年数,然后再进一步计算得到月份等。

以下是SQL代码,它提供了自sysdate以来的年数,月数和天数。 为input_birth_dateinput此格式的值(dd_mon_yy)。 注意:input相同的值(出生date)为年,月和日,如01年三月-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 

T-SQL中的DateTime值以浮点forms存储。 你可以减去对方的date,你现在有一个新的date,这是他们之间的时间跨度。

 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. 

对于那些想在表格中创build一个计算列来存储年龄的人:

 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 

有一个简单的方法,基于两天之间的小时,但结束date截断。

 SELECT CAST(DATEDIFF(hour,Birthdate,CAST(GETDATE() as Date))/8766.0 as INT) AS Age FROM <YourTable> 

这个已被certificate是非常准确和可靠的。 如果不是GETDATE()的内部CAST,它可能会在午夜前几个小时翻转生日,但是在CAST的时候,它恰好在午夜时分改变了。

这是我如何计算出生date和当前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 
 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