我有一张表格列出了人们的出生日期(目前是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
答案 0 :(得分:231)
闰年/日期存在问题以及以下方法,请参阅以下更新:
试试这个:
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)
更新这里有一些更准确的方法:
INT的最佳方法
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
答案 1 :(得分:110)
要把这个丢掉。如果convert使用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
答案 2 :(得分:37)
我在生产代码中使用了这个查询近10年:
SELECT FLOOR((CAST (GetDate() AS INTEGER) - CAST(Date_of_birth AS INTEGER)) / 365.25) AS Age
答案 3 :(得分:29)
上述许多解决方案都是错误的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
答案 4 :(得分:15)
您需要考虑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>
我改编自here
答案 5 :(得分:8)
编辑:这个答案是不正确的。 我把它留在这里作为警告任何想要使用dayofyear
的人,并在最后进行进一步的编辑。
如果像我一样,你不想除以分数天或冒险四舍五入/闰年错误,我赞成@Bacon Bits在https://stackoverflow.com/a/1572257/489865上面的帖子中发表评论,他说:
然后他提供:如果我们谈论人类年龄,你应该按照计算方式来计算 人类计算年龄。它与地球的速度无关 移动和与日历有关的一切。每次都一样 月和日作为出生日期,您将年龄增加1。 这意味着以下是最准确的,因为它反映了什么 人类的意思是他们说'#34;年龄&#34;。
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, ...)
&amp ;;按区域设置进行不更改SET DATEFIRST
。]
编辑 为什么dayofyear
出错?:正如用户@AeroX所评论的那样,如果出生/开始日期是非闰年2月之后,当前/结束日期是闰年时,年龄会提前一天递增,例如'2015-05-26'
,'2016-05-25'
给出1岁时的年龄,它应该仍为0.在不同年份比较dayofyear
显然是危险的。因此,毕竟使用MONTH()
和DAY()
是必要的。
答案 6 :(得分: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
这可以获得出生日期和当前日期之间的年份差异。如果生日还没有过去,那么它会减去一年。
始终准确 - 无论闰年如何或接近生日。
最重要的是 - 没有功能。
答案 7 :(得分:3)
我相信这与此处发布的其他内容相似......但是此解决方案适用于闰年示例02/29/1976至2011年1月3日,并且也适用于第一年的案例..喜欢07/04/2011至07/03/2012最后一篇关于闰年解决方案的帖子对于第一年的用例没有用。
SELECT FLOOR(DATEDIFF(DAY, @date1 , @date2) / 365.25)
找到here。
答案 8 :(得分: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
)
答案 9 :(得分:3)
怎么样:
DECLARE @DOB datetime
SET @DOB='19851125'
SELECT Datepart(yy,convert(date,GETDATE())-@DOB)-1900
这不会避免所有那些舍入,截断和解决问题吗?
答案 10 :(得分:2)
DECLARE @DOB datetime
set @DOB ='11/25/1985'
select floor(
( cast(convert(varchar(8),getdate(),112) as int)-
cast(convert(varchar(8),@DOB,112) as int) ) / 10000
)
来源:http://beginsql.wordpress.com/2012/04/26/how-to-calculate-age-in-sql-server/
答案 11 :(得分:2)
SELECT ID,
Name,
DATEDIFF(yy,CONVERT(DATETIME, DOB),GETDATE()) AS AGE,
DOB
FROM MyTable
答案 12 :(得分: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
答案 13 :(得分:1)
我已经做了很多思考和搜索,我有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中没有这样的东西。
答案 14 :(得分: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
答案 15 :(得分:0)
这似乎是一种适用于边缘情况的技术:年底和and年2月。
datediff(year,…,…)
的问题在于,它仅发现年份之间的差异,而不是实际日期,这在我看来有点天真。仅当出生日期为1月1日时,这才是可靠的。
解决方案是将出生日期时间扭曲到1月1日,并将要约日期等量。
由于使用using日的the年问题也不可靠,因此我使用月和日进行时间扭曲:
CREATE FUNCTION age(@then AS date,@now AS date) RETURNS int AS
BEGIN
DECLARE @month INT = month(@then)-1;
DECLARE @day INT = day(@then)-1;
SET @then=dateadd(month,-@month,@then);
SET @then=dateadd(day,-@day,@then);
SET @now=dateadd(month,-@month,@now;)
SET @now=dateadd(day,-@day,@now);
RETURN datediff(year,@then,@now);
END;
您当然可以更紧凑地编写它。如果您想玩得开心,甚至可以将其写成一行:
CREATE FUNCTION age(@then AS date,@now AS date) RETURNS int AS
BEGIN
RETURN datediff(
year,
dateadd(day,-day(@then)+1,dateadd(month,-month(@then)+1,@then)),
dateadd(day,-day(@then)+1,dateadd(month,-month(@then)+1,@now))
);
END;
但这只是炫耀,而且效率较低,因为它需要重新计算偏移量。
答案 16 :(得分:0)
尝试了许多方法之后,100%的时间使用现代的MS SQL FORMAT函数而不是转换为样式112.这两种方法都可以工作,但这是最少的代码。
任何人都可以找到不起作用的日期组合吗?我不认为有一个:)
--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
答案 17 :(得分:0)
select floor((datediff(day,0,@today) - datediff(day,0,@birthdate)) / 365.2425) as age
这里有很多365.25的答案。记住leap年是如何定义的:
答案 18 :(得分: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
答案 19 :(得分: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
答案 20 :(得分: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
答案 21 :(得分: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
答案 22 :(得分:0)
标记为正确的答案更接近准确性,但在以下情况下失败 - 其中出生年份为闰年,日期为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 ))
它几乎适用于所有场景,考虑到闰年,日期为29 bb等等。
如果这个公式有任何漏洞,请纠正我。
答案 23 :(得分: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
答案 24 :(得分:0)
这将正确处理生日和四舍五入的问题:
DECLARE @dob datetime
SET @dob='1992-01-09 00:00:00'
SELECT DATEDIFF(YEAR, '0:0', getdate()-@dob)
答案 25 :(得分: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
答案 26 :(得分: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'
答案 27 :(得分: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
答案 28 :(得分:-2)
你应该按照以下方式计算年数: -
select cast(datediff(DAY, '2000-03-01 10:00:01', '2013-03-01 10:00:00') / (365.23076923074) as int) as 'Age'
这很容易......
答案 29 :(得分:-2)
SELECT CAST(DATEDIFF(dy, @DOB, GETDATE()+1)/365.25 AS int)
答案 30 :(得分:-2)
select DATEDIFF(yy,@DATE,GETDATE()) -
case when DATEPART(mm,GETDATE())*100+DATEPART(dd,GETDATE())>=
DATEPART(mm,@DATE)*100+DATEPART(dd,@DATE) THEN 0
ELSE 1 END
答案 31 :(得分:-2)
select datediff(day,'1991-03-16',getdate()) \\for days,get date refers today date
select datediff(year,'1991-03-16',getdate()) \\for years
select datediff(month,'1991-03-16',getdate()) \\for month
答案 32 :(得分:-2)
我们使用了类似的东西,但是接下来的平均年龄:
ROUND(avg(CONVERT(int,DATEDIFF(hour,DOB,GETDATE())/8766.0)),0) AS AverageAge
注意,ROUND是在外面而不是在内部。这将允许AVG更准确,我们只转一次。让它更快。
答案 33 :(得分:-3)
你应该使用
从table_name中选择FLOOR(DATEDIFF(CURDATE(),DATE(DOB))/ 365.25);
这里CURDATE()使用当前日期,你可以用'yyyy-mm-dd'格式给出自己的日期
DATE(DOB)从您的列中提取yyyy-mm-dd年,该列为DATETIME格式
这里DOB是你的列名(但是在你的情况下你应该改变表来修改数据类型为DATETIME,这是nvarchar)
注意-
这个查询用在mysql中
这个全年的回归年龄
答案 34 :(得分:-4)
DECLARE @yourBirthDate DATETIME = '1987-05-25'
SELECT YEAR(DATEADD(DAY, DATEDIFF(DAY, @yourBirthDate, GETDATE()), CAST('0001-01-01' AS DATETIME2))) - 1