我有一个表,上面列出了人们的出生日期(目前是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

当前回答

编辑:这个答案不正确。我把它放在这里,作为对那些试图使用dayofyear的人的警告,并在最后进行了进一步的编辑。


如果你像我一样,不想用小数天数来除法,或者冒着四舍五入/闰年错误的风险,我为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(工作日,…)和SET DATEFIRST而改变。]


编辑:dayofyear错误的原因:正如用户@AeroX评论的那样,如果出生/开始日期在非闰年的2月之后,当当前/结束日期是闰年时,年龄将提前一天增加。'2015-05-26', '2016-05-25'给出的年龄是1,而它应该仍然是0。比较不同年份的日期显然是危险的。因此使用MONTH()和DAY()是必要的。

其他回答

你应该使用 select FLOOR(DATEDIFF(CURDATE(),DATE(DOB))/365.25) from table_name; 这里CURDATE()使用当前日期,您可以以'yyyy-mm-dd'格式给出自己的日期 DATE(DOB)从DATETIME格式的列中提取yyyy-mm-dd年 这里DOB是你的列名(但你应该改变表修改数据类型为DATETIME在你的情况下是nvarchar) 注意: 此查询用于mysql 这个年龄在全年

这个怎么样:

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

标记为正确的答案更接近准确,但在以下情况下,它失败了——出生年份是闰年,日在二月之后

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

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

OR

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

它几乎适用于所有场景,包括闰年、2月29日等。

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

闰年/日和以下方法有问题,请参阅下面的更新:

try this: 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 OUTPUT: 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

您可以将上面的10000更改为10000.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

简单明了

SELECT (YEAR(CURRENT_TIMESTAMP) - YEAR(birthday)) as age FROM db_deirvlon_monyo_users