Tengo una tabla que enumera a las 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?
Mis datos se ven 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
sql-server
sql-server-2005
select
date
Palanqueta
fuente
fuente
Respuestas:
Hay problemas con los años bisiestos y el siguiente método, consulte la actualización a continuación:
ACTUALIZACIÓN aquí hay algunos métodos más precisos:
MEJOR MÉTODO PARA AÑOS EN INT
puede cambiar lo anterior
10000
a10000.0
y obtener decimales, pero no va a ser tan preciso como el método siguiente.MEJOR MÉTODO PARA AÑOS EN DECIMAL
fuente
GETDATE()
) en '2013-07-04 23:59:59' dice que Tengo 27 años, mientras que en ese momento todavía no. Código de ejemplo: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
select datediff(year, '2000-01-05', '2018-01-04')
devuelve 18, no 17 como debería. Utilicé el ejemplo anterior bajo el título "MEJOR MÉTODO PARA AÑOS EN INT" y funciona perfectamente. ¡Gracias!Tengo que lanzar este por ahí. Si convierte 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
salida
fuente
code: SELECT [Age] = (0+ FORMAT(@as_of,'yyyyMMdd') - FORMAT(@bday,'yyyyMMdd') ) /10000 --The 0+ part tells SQL to calc the char(8) as numbers
He usado esta consulta en nuestro código de producción durante casi 10 años:
fuente
DATEDIFF(yy, @BirthDate, GETDATE()) - CASE WHEN (MONTH(@BirthDate) >= MONTH(GETDATE())) AND DAY(@BirthDate) > DAY(GETDATE()) THEN 1 ELSE 0 END
CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE())) THEN 1 ELSE 0 END
Muchas de las soluciones anteriores son incorrectas DateDiff (aa, @ Dob, @PassedDate) no considerará el mes y el día de ambas fechas. También tomar las partes del dardo y comparar solo funciona si se ordenan correctamente.
EL CÓDIGO SIGUIENTE FUNCIONA Y ES MUY SENCILLO:
fuente
0925
(o925
). Hace lo mismo con la fecha actual (como el 16 de diciembre1216
) y luego verifica si el valor entero DoB ya pasó. Para crear este número entero, el mes debe multiplicarse por 100.(CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000
Debe considerar la forma en que se redondea el comando con fecha.
Lo que adapté de aquí .
Tenga en cuenta que considerará el 28 de febrero como el cumpleaños de un salto por años no bisiestos, por ejemplo, una persona nacida el 29 de febrero de 2020 se considerará 1 año de edad el 28 de febrero de 2021 en lugar del 01 de marzo de 2021.
fuente
SELECT DATEDIFF(year, DOB, getdate()) + CASE WHEN (DATEADD(year,DATEDIFF(year, DOB, getdate()) , DOB) > getdate()) THEN - 1 ELSE 0 END)
EDITAR: ESTA RESPUESTA ES INCORRECTA. Lo dejo aquí como una advertencia a cualquiera que esté tentado a usar
dayofyear
, con una edición adicional al final.Si, como yo, no desea dividir por días fraccionarios o arriesgarse a errores de redondeo / año bisiesto, aplaudo el comentario de @Bacon Bits en una publicación anterior https://stackoverflow.com/a/1572257/489865 donde dice:
Luego ofrece:
Aquí hay varias sugerencias que involucran comparar el mes y el día (y algunas se equivocan, ¡no permiten la
OR
correcta aquí!). Pero nadie ha ofrecidodayofyear
, lo que parece tan simple y mucho más corto. Yo ofrezco:[Nota: ¡En ninguna parte de SQL BOL / MSDN se
DATEPART(dayofyear, ...)
documenta realmente lo que devuelve! Entiendo que es un número en el rango 1-366; lo más importante, no cambia según la configuración regional segúnDATEPART(weekday, ...)
&SET DATEFIRST
.]EDITAR: Por qué
dayofyear
sale mal : como ha comentado el usuario @AeroX, 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 ejemplo'2015-05-26'
,'2016-05-25'
da un 1 año de edad cuando aún debería ser 0. Comparar losdayofyear
años diferentes es claramente peligroso. Entonces usarMONTH()
yDAY()
es necesario después de todo.fuente
DayOfYear
método.dayofyear
, pero claramente editado para mostrar por qué sale mal. Espero que sea adecuado.Como no hay una respuesta simple que siempre proporcione la edad correcta, esto es lo que se me ocurrió.
Esto obtiene la diferencia de año 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 de la fecha de nacimiento.
Lo mejor de todo: sin función.
fuente
fuente
Qué pasa:
¿No evitaría eso todos esos problemas de redondeo, truncamiento y desajuste?
fuente
'1986-07-05 00:00:00'
para DOB y'2013-07-04 23:59:59'
para la hora actual.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 de año bisiesto no funcionó para ese caso de uso del primer año.
Encontrado aquí .
fuente
fuente
fuente: http://beginsql.wordpress.com/2012/04/26/how-to-calculate-age-in-sql-server/
fuente
code: SELECT [Age] = (0+ FORMAT(@ToDate,'yyyyMMdd') - FORMAT(@DOB,'yyyyMMdd') ) /10000
He pensado y buscado mucho sobre esto y tengo 3 soluciones que
Aquí hay valores de prueba:
Solución 1: Encontré este enfoque en una biblioteca js. Es mi favorito.
En realidad, agrega diferencia en años a DOB y si es mayor que la fecha actual, resta un año. Simple derecho? Lo único es que la diferencia en años se duplica aquí.
Pero si no necesita usarlo en línea, puede escribirlo así:
Solución 2: esta copiaba originalmente de @ bacon-bits. Es el más fácil de entender pero un poco largo.
Básicamente es calcular la edad como lo hacemos los humanos.
Solución 3: Mi amigo lo refactorizó en esto:
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
La función es para transformar cualquier valor que obtenga en -1, 0 o 1.CEILING(0.5 *
Es el mismoMath.max(0, value)
pero no existe tal cosa en SQL.fuente
fuente
Hay muchas respuestas 365.25 aquí. Recuerde cómo se definen los años bisiestos:
fuente
Qué tal esto:
fuente
Prueba esto
fuente
Prueba esta solución:
fuente
Esto manejará correctamente los problemas con el cumpleaños y el redondeo:
fuente
La solución de Ed Harper es la más simple que he encontrado y nunca devuelve la respuesta incorrecta cuando el mes y el día de las dos fechas están separados por 1 o menos días. Hice una ligera modificación para manejar edades negativas.
fuente
La respuesta marcada como correcta es más cercana a la precisión, pero falla en el siguiente escenario: donde el año de nacimiento es año bisiesto y el día es posterior al mes de febrero
O
- La siguiente solución me está dando resultados más precisos.
Funcionó en casi todos los escenarios, considerando el año bisiesto, la fecha como 29 de febrero, etc.
Corríjame si esta fórmula tiene alguna laguna.
fuente
floor
.fuente
Así es como calculo la edad dada una fecha de nacimiento y la fecha actual.
fuente
fuente
month(compare) > month(dob)
PEROday(compare) < day(dob)
, por ejemploselect dbo.AgeAtDate('2000-01-14', '2016-02-12')
.fuente
¿Qué pasa con una solución con solo funciones de fecha, no matemáticas, no te preocupes por el año bisiesto?
fuente
Después de probar MUCHOS métodos, esto funciona el 100% del tiempo usando la moderna función MS SQL FORMAT en lugar de convertir al estilo 112. Cualquiera funcionaría pero este es el código mínimo.
¿Alguien puede encontrar una combinación de fecha que no funciona? No creo que haya uno :)
fuente
Usamos algo como aquí, pero luego tomamos la edad promedio:
Observe que la RONDA está afuera más que adentro. Esto permitirá que el AVG sea más preciso y RODEEMOS solo una vez. Haciéndolo más rápido también.
fuente
fuente
fuente