fechas entre edad cantidad calcular años sql-server sql-server-2005 select date

sql-server - entre - cantidad de años en sql



Cómo calcular la edad(en años) según la fecha de nacimiento y getDate() (30)

Simplemente verifique si la respuesta a continuación es factible.

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 )

Tengo una tabla que enumera personas junto con su fecha de nacimiento (actualmente un nvarchar (25))

¿Cómo puedo convertir eso en una fecha y luego calcular su edad en años?

Mi información se ve de la siguiente manera

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

Me gustaría ver:

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


Así es como calculo la edad dada una fecha de nacimiento y una fecha actual.

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


Como no hay una respuesta simple que siempre dé la edad correcta, esto es lo que se me ocurrió.

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

Esto obtiene la diferencia anual entre la fecha de nacimiento y la fecha actual. Luego resta un año si la fecha de nacimiento aún no ha pasado.

Preciso todo el tiempo, independientemente de los años bisiestos o lo cerca que esté de la fecha de nacimiento.

Lo mejor de todo: sin función.


Creo que esto es similar a otros publicados aquí ... pero esta solución funcionó para los ejemplos del año bisiesto 29/02/1976 al 01/03/2011 y también funcionó para el caso durante el primer año ... como 07/04 / 2011 al 07/03/2012 que el último publicado sobre la solución del año bisiesto no funcionó para ese caso de uso del primer año.

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

Encontrado here .


Debe considerar la forma en que redondea el comando 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>

Que he adaptado desde here


Deberías usar
seleccione FLOOR (DATEDIFF (CURDATE (), DATE (DOB)) / 365.25) de table_name;
aquí CURDATE () usa la fecha actual, puede dar fecha propia en formato ''aaaa-mm-dd'' FECHA (DOB) extraer año yyyy-mm-dd de su columna que está en formato DATETIME aquí DOB es su nombre de columna (pero debe alter table para modificar el tipo de datos para que sea DATETIME en su caso, que es nvarchar) Nota: esta consulta se usa en mysql esta edad de retorno en todo el año


Esto solucionará correctamente los problemas con el cumpleaños y el redondeo:

DECLARE @dob datetime SET @dob=''1992-01-09 00:00:00'' SELECT DATEDIFF(YEAR, ''0:0'', getdate()-@dob)


Hay problemas con el año / día bisiesto y el siguiente método, consulte la actualización a continuación:

prueba esto:

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

SALIDA:

AgeYearsDecimal AgeYearsIntRound AgeYearsIntTrunc --------------------------------------- ---------------- ---------------- 17.767054 18 17 (1 row(s) affected)

ACTUALIZAR aquí hay algunos métodos más precisos:

MEJOR MÉTODO PARA AÑOS EN 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

puede cambiar los 10000 a 10000.0 y obtener decimales, pero no será tan preciso como el método a continuación.

MEJOR MÉTODO PARA AÑOS EN DECIMAL

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


He pensado mucho y buscado sobre esto y tengo 3 soluciones que

  • calcular la edad correctamente
  • son cortos (principalmente)
  • son (en su mayoría) muy comprensibles.

Aquí están los valores de prueba:

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

Solución 1: Encontré este enfoque en una biblioteca js. Es mi favorito.

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

De hecho, agrega diferencia en años a DOB y si es más grande que la fecha actual, resta un año. Simple ¿verdad? Lo único es que la diferencia en años se duplica aquí.

Pero si no necesita usarlo en línea, puede escribirlo así:

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

Solución 2: Esta, originalmente copié de @ bacon-bits. Es el más fácil de entender, pero un poco largo.

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

Básicamente es calcular la edad como lo hacemos los humanos.

Solución 3: mi amigo lo refactoó en esto:

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

Este es el más corto, pero es más difícil de entender. 50 es solo un peso, por lo que la diferencia de días solo es importante cuando los meses son iguales. SIGN función SIGN es para transformar cualquier valor que obtenga en -1, 0 o 1. CEILING(0.5 * es lo mismo que Math.max(0, value) pero no existe tal cosa en SQL.


La respuesta marcada como correcta está más cerca de la precisión, pero falla en el escenario siguiente, donde el año de nacimiento es el año bisiesto y el día posterior al mes de febrero.

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


O

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

- La siguiente solución me está dando resultados más precisos.

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

Funcionó en casi todos los escenarios, considerando año bisiesto, fecha como 29 feb, etc.

Por favor corrígeme si esta fórmula tiene alguna escapatoria.


La solución de Ed Harper es la más simple que he encontrado y que nunca arroja la respuesta incorrecta cuando el mes y el día de las dos fechas tienen 1 o menos días de diferencia. Hice una pequeña modificación para manejar las edades negativas.

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


Muchas de las soluciones anteriores son incorrectas DateDiff (yy, @ Dob, @PassedDate) no tendrá en cuenta el mes y el día de ambas fechas. También tomar las partes del dardo y comparar solo funciona si están ordenadas correctamente.

EL SIGUIENTE CÓDIGO FUNCIONA Y ES MUY SENCILLO:

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


Prueba esta solución:

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


Prueba esto

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


Qué pasa:

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

¿No evitaría eso todos esos problemas de redondeo, truncamiento y ataque?


Qué tal esto:

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


Tengo que tirar este por ahí. Si convert la fecha usando el estilo 112 (aaaammdd) a un número, puede usar un cálculo como este ...

(aaaaMMdd - aaaaMMdd) / 10000 = diferencia en años completos

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

salida

20091015 19800420 290595 29


Usamos algo así como aquí, pero luego tomamos la edad promedio:

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

Tenga en cuenta que la VUELTA está afuera en lugar de adentro. Esto permitirá que AVG sea más preciso y ROUND solo una vez. Haciéndolo más rápido también.


Utilicé esta consulta en nuestro código de producción durante casi 10 años:

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


deberías contar años de la siguiente manera:

select cast(datediff(DAY, ''2000-03-01 10:00:01'', ''2013-03-01 10:00:00'') / (365.23076923074) as int) as ''Age''

es muy fácil...


EDITAR: ESTA RESPUESTA ES INCORRECTA. Lo dejo aquí como una advertencia para cualquier persona tentado de usar dayofyear , con una edición adicional al final.

Si, como yo, no desea dividir por días fraccionarios ni arriesgarse a errores de redondeo / año bisiesto, aplaudo a @Bacon Bits al comentar en una publicación anterior https://.com/a/1572257/489865 donde dice:

Si hablamos de la edad humana, deberías calcularla de la misma manera que los humanos calculan la edad. No tiene nada que ver con qué tan rápido se mueve la tierra y todo lo que tiene que ver con el calendario. Cada vez que transcurre el mismo mes y día que la fecha de nacimiento, se aumenta la edad en 1. Esto significa que la siguiente es la más precisa porque refleja lo que los humanos quieren decir cuando dicen "edad".

Luego él ofrece:

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

Aquí hay varias sugerencias que implican comparar el mes y el día (¡y algunos lo malinterpretan, al no permitir el OR como aquí correctamente!). Pero nadie ofreció dayofyear , que parece tan simple y mucho más corto. Yo ofrezco:

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

[Nota: ¡En ninguna parte de SQL BOL / MSDN está realmente documentado DATEPART(dayofyear, ...) ! Entiendo que es un número en el rango 1-366; lo más importante, no cambia según la configuración regional según DATEPART(weekday, ...) & SET DATEFIRST .]

EDITAR: Por qué el día de dayofyear falla : como el usuario @AeroX comentó, si la fecha de nacimiento / inicio es posterior a febrero en un año no bisiesto, la edad se incrementa un día antes cuando la fecha actual / final es un año bisiesto, por ej. ''2015-05-26'' , ''2016-05-25'' da una edad de 1 cuando aún debería ser 0. Comparar el dayofyear en años diferentes es claramente peligroso. Entonces, usar MONTH() y DAY() es necesario después de todo.


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


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



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


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


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


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


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


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