如何根据出生日期和getDate()计算年龄(以年为单位)


171

我有一张表,列出人以及他们的出生日期(目前为nvarchar(25))

如何将其转换为日期,然后以年为单位计算年龄?

我的数据如下

ID    Name   DOB
1     John   1992-01-09 00:00:00
2     Sally  1959-05-20 00:00:00

我想看看:

ID    Name   AGE  DOB
1     John   17   1992-01-09 00:00:00
2     Sally  50   1959-05-20 00:00:00

16
为什么使用nvarchar(25)而不是数据库的本机日期或日期时间类型将日期值存储为字符串?
杰斯珀,

这个问题被标记为2005而不是2008,因此无法使用原始的“ Date”类型,但肯定是日期时间,因此可以说是SmallDateTime,因为您不需要准确性。
安德鲁

嗨,将日期保留为varchar的原因是因为我是从非SQL Server模式导入的,因此在将它们导入为datetime(以及其他日期格式)和将varchar转换为OK时存在一些问题
Jimmy

7
@ James.Elsey,所以您在导入时遇到问题,因此所有日期都有效吗?除非您对varchar使用datetime或smalldatetime,否则无法确定,虽然可以使导入正常工作,但可能还会遇到其他问题。另外,我永远也不会存储年龄,它每天都会更改,请使用View
KM。

@KM是的,将数据作为日期导入存在问题,当时唯一可行的解​​决方案是将其作为nvarchars导入。这种选择将成为每夜工作的一部分,因此存储年龄不成问题
Jimmy

Answers:


256

leap年/日和以下方法存在问题,请参阅以下更新:

试试这个:

DECLARE @dob  datetime
SET @dob='1992-01-09 00:00:00'

SELECT DATEDIFF(hour,@dob,GETDATE())/8766.0 AS AgeYearsDecimal
    ,CONVERT(int,ROUND(DATEDIFF(hour,@dob,GETDATE())/8766.0,0)) AS AgeYearsIntRound
    ,DATEDIFF(hour,@dob,GETDATE())/8766 AS AgeYearsIntTrunc

输出:

AgeYearsDecimal                         AgeYearsIntRound AgeYearsIntTrunc
--------------------------------------- ---------------- ----------------
17.767054                               18               17

(1 row(s) affected)

更新这里是一些更准确的方法:

年度最佳方法

DECLARE @Now  datetime, @Dob datetime
SELECT   @Now='1990-05-05', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1990-05-04', @Dob='1980-05-05'  --results in  9
--SELECT @Now='1989-05-06', @Dob='1980-05-05'  --results in  9
--SELECT @Now='1990-05-06', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1990-12-06', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1991-05-04', @Dob='1980-05-05'  --results in 10

SELECT
    (CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000 AS AgeIntYears

您可以将以上内容更改1000010000.0并获取小数,但是它不如下面的方法准确。

十年最佳方法

DECLARE @Now  datetime, @Dob datetime
SELECT   @Now='1990-05-05', @Dob='1980-05-05' --results in 10.000000000000
--SELECT @Now='1990-05-04', @Dob='1980-05-05' --results in  9.997260273973
--SELECT @Now='1989-05-06', @Dob='1980-05-05' --results in  9.002739726027
--SELECT @Now='1990-05-06', @Dob='1980-05-05' --results in 10.002739726027
--SELECT @Now='1990-12-06', @Dob='1980-05-05' --results in 10.589041095890
--SELECT @Now='1991-05-04', @Dob='1980-05-05' --results in 10.997260273973

SELECT 1.0* DateDiff(yy,@Dob,@Now) 
    +CASE 
         WHEN @Now >= DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)) THEN  --birthday has happened for the @now year, so add some portion onto the year difference
           (  1.0   --force automatic conversions from int to decimal
              * DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)),@Now) --number of days difference between the @Now year birthday and the @Now day
              / DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),1,1),DATEFROMPARTS(DATEPART(yyyy,@Now)+1,1,1)) --number of days in the @Now year
           )
         ELSE  --birthday has not been reached for the last year, so remove some portion of the year difference
           -1 --remove this fractional difference onto the age
           * (  -1.0   --force automatic conversions from int to decimal
                * DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)),@Now) --number of days difference between the @Now year birthday and the @Now day
                / DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),1,1),DATEFROMPARTS(DATEPART(yyyy,@Now)+1,1,1)) --number of days in the @Now year
             )
     END AS AgeYearsDecimal

24
这也不是确切的解决方案。如果我将自己的@dob设为'1986-07-05 00:00:00',然后GETDATE()在'2013-07-04 23:59:59'上执行此操作(使用其他变量代替),它会说我27岁,那一刻,我还没有。示例代码: declare @startDate nvarchar(100) = '1986-07-05 00:00:00' declare @endDate nvarchar(100) = '2013-07-04 23:59:59' SELECT DATEDIFF(hour,@startDate,@endDate)/8766.0 AS AgeYearsDecimal ,CONVERT(int,ROUND(DATEDIFF(hour,@startDate,@endDate)/8766.0,0)) AS AgeYearsIntRound ,DATEDIFF(hour,@startDate,@endDate)/8766 AS AgeYearsIntTrunc
bartlaarhoven 2013年

20
这是不准确的,因为它假设每年8766小时,即365.25天。由于没有365.25天的年份,因此在此人的生日附近这是不正确的,而不是正确的频率。 这种方法仍将更加准确。
培根Bits 2014年

1
@Bacon Bits第二条评论-当当前日期接近一个人的出生日期时,这通常是错误的。
闪光

2
我认为第一段文字使这个答案令人困惑。如果您更新后的方法没有leap年的问题,我建议(如果您真的想保留它)将其移至答案的底部。
ajbeaven

1
如果您想进行精确计算,则DATEDIFF不会使用@ShailendraMishra,因为它近似于天,等等。例如,select datediff(year, '2000-01-05', '2018-01-04')返回18,而不是应该返回的17。我在标题为“以年为单位的最佳方法”下使用了上面的示例,它可以很好地工作。谢谢!
openwonk

132

要把这个扔在那里。如果使用112样式(yyyymmdd)日期转换为数字,则可以使用如下计算方式...

(yyyyMMdd-yyyyMMdd)/ 10000 =全年差异

declare @as_of datetime, @bday datetime;
select @as_of = '2009/10/15', @bday = '1980/4/20'

select 
    Convert(Char(8),@as_of,112),
    Convert(Char(8),@bday,112),
    0 + Convert(Char(8),@as_of,112) - Convert(Char(8),@bday,112), 
    (0 + Convert(Char(8),@as_of,112) - Convert(Char(8),@bday,112)) / 10000

输出

20091015    19800420    290595  29

14
解决所有the年问题的方法几乎是神奇的。可能值得注意的是112是CONVERT函数的特殊数字,该函数将日期格式设置为yyyymmdd。当您看到它时,对于每个人来说可能并不明显。
德里克·托姆斯

5
你是个天才!
ercan

当我们用来查找年龄的日期与我们进行比较的日期是同一天时,我的团队遇到了一个问题。我们注意到,当他们在同一天(如果年龄会变得奇怪)时,年龄将减少一岁。这很好用!
Sheek Geek,

1
这是正确的答案-请如此标记。
Snympi '18年

4
对于SQL Server 2012+中这种完全相同的计算方法,最简单/最短的代码是code: SELECT [Age] = (0+ FORMAT(@as_of,'yyyyMMdd') - FORMAT(@bday,'yyyyMMdd') ) /10000 --The 0+ part tells SQL to calc the char(8) as numbers
ukgav

44

我在生产代码中使用此查询已有近10年的时间:

SELECT FLOOR((CAST (GetDate() AS INTEGER) - CAST(Date_of_birth AS INTEGER)) / 365.25) AS Age

6
不错,但不是100%,2007/10/16将在2009/10/15报告年龄为2岁
Andrew

4
Doh,我们遗漏了明显的东西,它是在中午之后,getdate返回一个int,所以当然会四舍五入。我复制并粘贴了您的答案并运行它,因此自动使用了getdate而不是原义。
安德鲁(Andrew)

2
优雅而简单。谢谢!
William MB

9
如果我们谈论的是人类年龄,则应该按照人类计算年龄的方式进行计算。它与地球运动的速度无关,也与日历无关。每次与出生日期相同的月份和日期过去时,您将年龄增加1。这意味着以下内容最准确,因为它反映了人类说“年龄”时的意思:DATEDIFF(yy, @BirthDate, GETDATE()) - CASE WHEN (MONTH(@BirthDate) >= MONTH(GETDATE())) AND DAY(@BirthDate) > DAY(GETDATE()) THEN 1 ELSE 0 END
培根片刻2014年

5
抱歉,语法错误。 CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE())) THEN 1 ELSE 0 END
培根片2014年

31

因此,以上许多解决方案都是错误的DateDiff(yy,@ Dob,@PassedDate)将不考虑两个日期的月份和日期。另外,将飞镖零件和仅在订购正确的情况下进行比较才有效。

以下代码可以正常工作:

create function [dbo].[AgeAtDate](
    @DOB    datetime,
    @PassedDate datetime
)

returns int
with SCHEMABINDING
as
begin

declare @iMonthDayDob int
declare @iMonthDayPassedDate int


select @iMonthDayDob = CAST(datepart (mm,@DOB) * 100 + datepart  (dd,@DOB) AS int) 
select @iMonthDayPassedDate = CAST(datepart (mm,@PassedDate) * 100 + datepart  (dd,@PassedDate) AS int) 

return DateDiff(yy,@DOB, @PassedDate) 
- CASE WHEN @iMonthDayDob <= @iMonthDayPassedDate
  THEN 0 
  ELSE 1
  END

End

为什么要乘以100?当我尝试在数据库中复制代码库中存在的内容时,这对我有用—但是我无法解释您的功能。这可能是一个愚蠢的问题:)

6
谢谢!正是我在这里期望的代码。这是该线程中唯一没有(丑陋)字符串转换的完全正确的代码!@Jen需要DoB的月份和日期(如9月25日)并将其转换为整数值0925(或925)。它与当前日期相同(例如12月16日变为1216),然后检查DoB整数值是否已经过去。为了创建这个整数,当月应乘以100。
bartlaarhoven

由于@bartlaarhoven :)

我只想提一下,尽管这确实避免了字符串转换,但它进行了大量强制转换。我的测试表明,它并没有比dotjoe的答案快很多,并且代码更加冗长。
StriplingWarrior

接受的答案具有更简单的INT答案:(CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000
KM。

19

您需要考虑datediff命令的舍入方式。

SELECT CASE WHEN dateadd(year, datediff (year, DOB, getdate()), DOB) > getdate()
            THEN datediff(year, DOB, getdate()) - 1
            ELSE datediff(year, DOB, getdate())
       END as Age
FROM <table>

我从这里适应

请注意,它将以2月28日为跨越非years年的生日,例如,2020年2月29日出生的人将在2021年2月28日被视为1岁,而不是2021年3月1日。


@安德鲁(Andrew)-更正了-我错过了一次换人的机会
艾德·哈珀

1
简体字版SELECT DATEDIFF(year, DOB, getdate()) + CASE WHEN (DATEADD(year,DATEDIFF(year, DOB, getdate()) , DOB) > getdate()) THEN - 1 ELSE 0 END)
彼得

这是正确的方法;我不明白为什么会如此大批抨击骇客。
萨尔曼

8

编辑:此答案不正确。 我将其留在此处作为对尝试使用的人的警告dayofyear,最后进行进一步的编辑。


如果像我一样,如果您不想除以小数天或四舍五入/ year年错误,我会在https://stackoverflow.com/a/1572257/489865上方的帖子中对@Bacon Bits表示赞赏,他说:

如果我们谈论的是人类年龄,则应该按照人类计算年龄的方式进行计算。它与地球运动的速度无关,也与日历无关。每次与出生日期相同的月份和日期过去时,您将年龄增加1。这意味着以下内容最准确,因为它反映了人类说“年龄”时的意思。

然后,他提供:

DATEDIFF(yy, @date, GETDATE()) -
CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE()))
THEN 1 ELSE 0 END

这里有一些建议涉及月与日之间的比较(有些建议做错了,这里没有OR正确输入!)。但是没有人提供dayofyear,它看起来如此简单且短得多。我提供:

DATEDIFF(year, @date, GETDATE()) -
CASE WHEN DATEPART(dayofyear, @date) > DATEPART(dayofyear, GETDATE()) THEN 1 ELSE 0 END

[注意:在SQL BOL / MSDN中,DATEPART(dayofyear, ...)实际记录的返回值都没有!我知道它是1--366范围内的数字;最重要的是没有按区域按更改DATEPART(weekday, ...)SET DATEFIRST]


编辑: 为什么dayofyear不顺心:由于用户@AeroX曾这样评价,如果出生/开始日期是2月后在非闰年,年龄递增月初的一天,当电流/结束日期为闰年,例如'2015-05-26''2016-05-25'给出了一个年龄1,但仍应为0。比较dayofyear不同年份显然很危险。因此使用MONTH()DAY()毕竟是必要的。


应该对此进行投票,甚至将其标记为答案。它简短,优雅并且在逻辑上是正确的。
z00l

1
对于使用二月法出生的每个人,使用该DayOfYear方法时,其年龄在每个leap年都提前一天增加。
AeroX

4
@AeroX感谢您发现此漏洞。我决定将解决方案作为警告,以警告任何可能或曾经使用过的人dayofyear,但请对其进行清晰地编辑以表明其出问题的原因。我希望那是合适的。
JonBrave '16

5

由于没有一个简单的答案可以始终给出正确的年龄,所以这就是我的想法。

SELECT DATEDIFF(YY, DateOfBirth, GETDATE()) - 
     CASE WHEN RIGHT(CONVERT(VARCHAR(6), GETDATE(), 12), 4) >= 
               RIGHT(CONVERT(VARCHAR(6), DateOfBirth, 12), 4) 
     THEN 0 ELSE 1 END AS AGE 

这将获得出生日期与当前日期之间的年份差。如果尚未过生日,则减去一年。

始终保持准确状态-不管leap年或出生日期有多近。

最好的-没有功能。


3
SELECT ID,
Name,
DATEDIFF(yy,CONVERT(DATETIME, DOB),GETDATE()) AS AGE,
DOB
FROM MyTable

1
您希望将getdate作为第二个参数而不是第一个参数,否则会得到负数结果,并且datediff会四舍五入,因此选择datediff(yy,'20081231',getdate())将报告年龄为1,但它们只有10个月大。
安德鲁

1
此计算为今年尚未过生日的人提供了错误的计算。

3

关于什么:

DECLARE @DOB datetime
SET @DOB='19851125'   
SELECT Datepart(yy,convert(date,GETDATE())-@DOB)-1900

难道不能避免所有这些舍入,截断和抵消问题吗?


您的计算不准确。例如:如果您使用'1986-07-05 00:00:00'DOB和'2013-07-04 23:59:59'当前时间,则失败。
drinovc

@ub_coding您是否提供答案或提出其他问题?
亚伦C

这:DECLARE @DOB datetime SET @ DOB ='19760229'SELECT Datepart(yy,convert(datetime,'19770228')-@ DOB)-1900 = 1主要问题是大多数解决方案的Fev 29差距,这就是解释舍入舍入等。
莱昂纳多马基斯迪索扎

3

我相信这与此处发布的其他解决方案类似。...但是此解决方案适用于examples年示例02/29/1976至03/03/2011,也适用于第一年的案例。例如07/04 / 2011到2012年7月3日,最后一篇关于posted年解决方案的文章不适用于该第一年用例。

SELECT FLOOR(DATEDIFF(DAY, @date1 , @date2) / 365.25)

这里找到。


3

只需检查以下答案是否可行。

DECLARE @BirthDate DATE = '09/06/1979'

SELECT 
 (
 YEAR(GETDATE()) - YEAR(@BirthDate) - 
 CASE  WHEN (MONTH(GETDATE()) * 100) + DATEPART(dd, GETDATE()) >     
 (MONTH(@BirthDate) * 100) + DATEPART(dd, @BirthDate)
 THEN 1             
 ELSE 0             
 END        
 )


2

我已经做了很多思考和搜索,有3个解决方案

  • 正确计算年龄
  • 矮(大部分)
  • (大部分)是可以理解的。

以下是测试值:

DECLARE @NOW DATETIME = '2013-07-04 23:59:59' 
DECLARE @DOB DATETIME = '1986-07-05' 

解决方案1:我在一个js库中找到了这种方法。这是我的最爱。

DATEDIFF(YY, @DOB, @NOW) - 
  CASE WHEN DATEADD(YY, DATEDIFF(YY, @DOB, @NOW), @DOB) > @NOW THEN 1 ELSE 0 END

它实际上是在DOB中增加了几年的差异,如果它大于当前日期,则减去一年。简单吧?唯一的是,这里的年份差异是重复的。

但是,如果您不需要内联使用它,则可以这样编写:

DECLARE @AGE INT = DATEDIFF(YY, @DOB, @NOW)
IF DATEADD(YY, @AGE, @DOB) > @NOW
SET @AGE = @AGE - 1

解决方案2:我最初是从@ bacon-bits复制的。这是最容易理解的内容,但是有点长。

DATEDIFF(YY, @DOB, @NOW) - 
  CASE WHEN MONTH(@DOB) > MONTH(@NOW) 
    OR MONTH(@DOB) = MONTH(@NOW) AND DAY(@DOB) > DAY(@NOW) 
  THEN 1 ELSE 0 END

它基本上像人类一样计算年龄。


解决方案3:我的朋友将其重构为:

DATEDIFF(YY, @DOB, @NOW) - 
  CEILING(0.5 * SIGN((MONTH(@DOB) - MONTH(@NOW)) * 50 + DAY(@DOB) - DAY(@NOW)))

这是最短的,但最难理解。50只是一个重量,所以只有在月份相同的情况下,日差才重要。SIGN函数用于将它获取的任何值转换为-1、0或1。CEILING(0.5 *Math.max(0, value)函数与SQL 相同,但没有这种东西。


1
CASE WHEN datepart(MM, getdate()) < datepart(MM, BIRTHDATE) THEN ((datepart(YYYY, getdate()) - datepart(YYYY, BIRTH_DATE)) -1 )
     ELSE 
        CASE WHEN datepart(MM, getdate()) = datepart(MM, BIRTHDATE)
            THEN 
                CASE WHEN datepart(DD, getdate()) < datepart(DD, BIRTHDATE) THEN ((datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE)) -1 )
                    ELSE (datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE))
                END
        ELSE (datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE)) END            
    END


0

这个怎么样:

SET @Age = CAST(DATEDIFF(Year, @DOB, @Stamp) as int)
IF (CAST(DATEDIFF(DAY, DATEADD(Year, @Age, @DOB), @Stamp) as int) < 0) 
    SET @Age = @Age - 1

0

试试这个

DECLARE @date datetime, @tmpdate datetime, @years int, @months int, @days int
SELECT @date = '08/16/84'

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 Convert(Varchar(Max),@years)+' Years '+ Convert(Varchar(max),@months) + ' Months '+Convert(Varchar(Max), @days)+'days'

0

试试这个解决方案:

declare @BirthDate datetime
declare @ToDate datetime

set @BirthDate = '1/3/1990'
set @ToDate = '1/2/2008'
select @BirthDate [Date of Birth], @ToDate [ToDate],(case when (DatePart(mm,@ToDate) <  Datepart(mm,@BirthDate)) 
        OR (DatePart(m,@ToDate) = Datepart(m,@BirthDate) AND DatePart(dd,@ToDate) < Datepart(dd,@BirthDate))
        then (Datepart(yy, @ToDate) - Datepart(yy, @BirthDate) - 1)
        else (Datepart(yy, @ToDate) - Datepart(yy, @BirthDate))end) Age

0

这样可以正确处理生日和取整问题:

DECLARE @dob  datetime
SET @dob='1992-01-09 00:00:00'

SELECT DATEDIFF(YEAR, '0:0', getdate()-@dob)

2
无法正确处理leap年SELECT DATEDIFF(YEAR,'0:0',convert(datetime,'2014-02-28')-'2012-02-29')给出2,但应仅为1
Peter Kerr

0

埃德·哈珀(Ed Harper)的解决方案是我发现的最简单的解决方案,当两个日期的月份和日期相隔1天或更短时,它永远不会返回错误的答案。我做了一些修改以应对负面的年龄。

DECLARE @D1 AS DATETIME, @D2 AS DATETIME
SET @D2 = '2012-03-01 10:00:02'
SET @D1 = '2013-03-01 10:00:01'
SELECT
   DATEDIFF(YEAR, @D1,@D2)
   +
   CASE
      WHEN @D1<@D2 AND DATEADD(YEAR, DATEDIFF(YEAR,@D1, @D2), @D1) > @D2
      THEN - 1
      WHEN @D1>@D2 AND DATEADD(YEAR, DATEDIFF(YEAR,@D1, @D2), @D1) < @D2
      THEN 1
      ELSE 0
   END AS AGE

0

标记为正确的答案更接近准确性,但是在以下情况下却无法通过- 出生年份为Le年,并且日期在2月之后

declare @ReportStartDate datetime = CONVERT(datetime, '1/1/2014'),
@DateofBirth datetime = CONVERT(datetime, '2/29/1948')

FLOOR(DATEDIFF(HOUR,@DateofBirth,@ReportStartDate )/8766)


要么

FLOOR(DATEDIFF(HOUR,@DateofBirth,@ReportStartDate )/8765.82) -- Divisor is more accurate than 8766

-以下解决方案为我提供了更准确的结果。

FLOOR(DATEDIFF(YEAR,@DateofBirth,@ReportStartDate) - (CASE WHEN DATEADD(YY,DATEDIFF(YEAR,@DateofBirth,@ReportStartDate),@DateofBirth) > @ReportStartDate THEN 1 ELSE 0 END ))

考虑到leap年,日期为2月29日等,它几乎可以在所有情况下使用。

如果这个公式有漏洞,请纠正我。


最终公式几乎完全像此答案stackoverflow.com/a/1572235/168747所示。但是这里的可读性较差并且包含不必要的内容floor
Marek

0
Declare @dob datetime
Declare @today datetime

Set @dob = '05/20/2000'
set @today = getdate()

select  CASE
            WHEN dateadd(year, datediff (year, @dob, @today), @dob) > @today 
            THEN datediff (year, @dob, @today) - 1
            ELSE datediff (year, @dob, @today)
        END as Age

0

这是给定出生日期和当前日期的年龄的计算方法。

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

0
CREATE function dbo.AgeAtDate(
    @DOB    datetime,
    @CompareDate datetime
)

returns INT
as
begin

return CASE WHEN @DOB is null
THEN 
    null
ELSE 
DateDiff(yy,@DOB, @CompareDate) 
- CASE WHEN datepart(mm,@CompareDate) > datepart(mm,@DOB) OR (datepart(mm,@CompareDate) = datepart(mm,@DOB) AND datepart(dd,@CompareDate) >= datepart(dd,@DOB))
  THEN 0 
  ELSE 1
  END
END
End

GO

-1:将是错误的任何时候month(compare) > month(dob)BUT day(compare) < day(dob),例如select dbo.AgeAtDate('2000-01-14', '2016-02-12')
JonBrave '16

您是对的,谢谢您的支持,此功能已更新
-Vova

0
DECLARE @FromDate DATETIME = '1992-01-2623:59:59.000', 
        @ToDate   DATETIME = '2016-08-10 00:00:00.000',
        @Years INT, @Months INT, @Days INT, @tmpFromDate DATETIME
SET @Years = DATEDIFF(YEAR, @FromDate, @ToDate)
 - (CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, @FromDate, @ToDate),
          @FromDate) > @ToDate THEN 1 ELSE 0 END) 


SET @tmpFromDate = DATEADD(YEAR, @Years , @FromDate)
SET @Months =  DATEDIFF(MONTH, @tmpFromDate, @ToDate)
 - (CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH, @tmpFromDate, @ToDate),
          @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 

SET @tmpFromDate = DATEADD(MONTH, @Months , @tmpFromDate)
SET @Days =  DATEDIFF(DAY, @tmpFromDate, @ToDate)
 - (CASE WHEN DATEADD(DAY, DATEDIFF(DAY, @tmpFromDate, @ToDate),
          @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 

SELECT @FromDate FromDate, @ToDate ToDate, 
       @Years Years,  @Months Months, @Days Days

0

只包含日期函数而不是数学的解决方案,不用担心leap年

CREATE FUNCTION dbo.getAge(@dt datetime) 
RETURNS int
AS
BEGIN
    RETURN 
        DATEDIFF(yy, @dt, getdate())
        - CASE 
            WHEN 
                MONTH(@dt) > MONTH(GETDATE()) OR 
                (MONTH(@dt) = MONTH(GETDATE()) AND DAY(@dt) > DAY(GETDATE())) 
            THEN 1 
            ELSE 0 
        END
END

0

在尝试了许多方法之后,使用现代MS SQL FORMAT函数而不是转换为样式112,可以100%地起作用。这两种方法都可以,但这是最少的代码。

谁能找到无效的日期组合?我认为没有一个:)

--Set parameters, or choose from table.column instead:

DECLARE @DOB    DATE = '2000/02/29' -- If @DOB is a leap day...
       ,@ToDate DATE = '2018/03/01' --...there birthday in this calculation will be 

--0+ part tells SQL to calc the char(8) as numbers:
SELECT [Age] = (0+ FORMAT(@ToDate,'yyyyMMdd') - FORMAT(@DOB,'yyyyMMdd') ) /10000

-2

我们使用了类似此处的方法,但采用了平均年龄:

ROUND(avg(CONVERT(int,DATEDIFF(hour,DOB,GETDATE())/8766.0)),0) AS AverageAge

注意,回合在外面而不是里面。这将使AVG更加准确,而我们只回合一次。也使其更快。



-2
SELECT CAST(DATEDIFF(dy, @DOB, GETDATE()+1)/365.25 AS int)

我看到了反对票,但没有看到证明这一点被打破的例子。
Alex
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.