Hola, chicos,
Todo está bien ?
En este post me gustaría mostrar cómo calcular la diferencia en años (edad) entre dos fechas en SQL Server, mostrando algunas soluciones y un análisis de rendimiento entre estas opciones para identificar la forma más eficaz de realizar este cálculo.
Como sabes, para solucionar este problema no basta con realizar un simple DATEDIFF(YEAR, @Dt_Inicial, @Dt_Final), ya que la función DATEDIFF(YEAR…) devolverá la diferencia en años sin considerar si las fechas ya “cumplieron su aniversario”.
En una explicación sencilla, la función DATEDIFF(AÑO…) devuelve el cálculo AÑO(@Dt_Final) – AÑO(@Dt_Inicial).
Demostraré por qué esto no funciona para el cálculo de la edad:

Como puede ver, no basta con utilizar la función DATEDIFF(YEAR..) para calcular la edad. En el primer ejemplo, con solo 1 día de diferencia entre las fechas, la función me devolvió que esa diferencia es de 1 año.
En el segundo ejemplo, la función devuelve 30 años de diferencia, pero la primera fecha es el 09/04 y la segunda es el 28/05, es decir, aún no ha cumplido 1 año y el valor correcto sería 29 años.
Cómo calcular la edad usando T-SQL
Ahora demostraré dos formas sencillas de calcular la edad utilizando Transact-SQL.
Cálculo de edad utilizando Transact-SQL y CASE
Para realizar este cálculo, calculamos la diferencia en años entre las fechas y disminuimos en 1 si el mes y día de la fecha inicial es menor que el mes y día de la fecha final.
CREATE FUNCTION [dbo].[fncCalcula_Idade] (@Dt_Nascimento DATETIME, @Dt_Hoje DATETIME)
RETURNS INT
AS BEGIN
RETURN DATEDIFF(YEAR, @Dt_Nascimento, @Dt_Hoje) + CASE WHEN (MONTH(@Dt_Nascimento) > MONTH(@Dt_Hoje) OR (MONTH(@Dt_Nascimento) = MONTH(@Dt_Hoje) AND DAY(@Dt_Nascimento) > DAY(@Dt_Hoje))) THEN -1 ELSE 0 END
END
Cálculo de edad usando Transact-SQL y división por 365,25
Para realizar este cálculo calculamos la diferencia en días entre las fechas y dividimos este valor entre 365,25. ¿Pero por qué este 0,25? La respuesta es sencilla... Años bisiestos. Esta "técnica" está escrita por mi amigo y especialista en BI, Lucas Galón.
CREATE FUNCTION [dbo].[fncCalcula_Idade2] (@Dt_Nascimento DATETIME, @Dt_Hoje DATETIME)
RETURNS INT
AS BEGIN
RETURN DATEDIFF(DAY, @Dt_Nascimento, @Dt_Hoje) / 365.25
END
Cómo calcular la edad usando CLR
Ahora demostraré dos formas sencillas de calcular la edad utilizando CLR, cuyo objetivo es obtener una gran ganancia de rendimiento gracias a las optimizaciones del lenguaje C# y Microsoft .NET Framework.
Cálculo de edad mediante CLR y cálculos manuales
Para realizar este cálculo, calculamos la diferencia en años entre las fechas y disminuimos en 1 si el mes y día de la fecha inicial es menor que el mes y día de la fecha final.
using System.Data.SqlTypes;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 fncCalcula_Idade(SqlDateTime Dt_Nascimento, SqlDateTime Dt_Hoje)
{
if (Dt_Nascimento.IsNull || Dt_Hoje.IsNull)
return SqlInt32.Null;
var anos = Dt_Hoje.Value.Year - Dt_Nascimento.Value.Year;
if (Dt_Hoje.Value.Month < Dt_Nascimento.Value.Month || (Dt_Hoje.Value.Month == Dt_Nascimento.Value.Month && Dt_Hoje.Value.Day < Dt_Nascimento.Value.Day))
anos--;
return anos;
}
}
Cálculo de edad utilizando CLR y división por 365,25
Para realizar este cálculo, calculamos la diferencia en días entre las fechas y dividimos este valor entre 365,25, como se mencionó anteriormente, pero ahora usando el CLR.
using System;
using System.Data.SqlTypes;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 fncCalcula_Idade2(SqlDateTime Dt_Nascimento, SqlDateTime Dt_Hoje)
{
return (Dt_Nascimento.IsNull || Dt_Hoje.IsNull) ? SqlInt32.Null : Convert.ToInt32(Math.Floor((Dt_Hoje.Value - Dt_Nascimento.Value).TotalDays / 365.25));
}
}
Resultados de las funciones presentadas.

Pruebas de rendimiento
Ahora que he demostrado algunas soluciones diferentes para calcular la edad en SQL Server, compararé el rendimiento de todas ellas y comprobaré cuál es la más eficaz.
Como ya mencioné en el post. SQL Server: comparación de rendimiento entre la función escalar y la función escalar CLR, funciones CLR generalmente funcionará mejor que las funciones T-SQL, al mismo tiempo que las funciones en línea (sin crear UDF) generalmente funcionan mejor que las funciones CLR. Veamos cómo le va a cada solución.
Para estas pruebas, usaré una base de 131,072 fechas aleatorias para calcular la edad en comparación con la fecha actual, y el script para generar esta base lo pondré a disposición a continuación:
Script para generar masa de prueba.
IF (OBJECT_ID('dbo.fncRand') IS NOT NULL) DROP FUNCTION dbo.fncRand
GO
CREATE FUNCTION dbo.fncRand(@Numero BIGINT)
RETURNS BIGINT
AS
BEGIN
RETURN (ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0) * @Numero
END
GO
IF (OBJECT_ID('dbo.Datas') IS NOT NULL) DROP TABLE dbo.Datas
CREATE TABLE dbo.Datas (
Data_Inicio DATETIME
)
DECLARE
@Contador INT = 1,
@Total INT = 17
INSERT INTO dbo.Datas ( Data_Inicio )
VALUES ( '1970-01-01' )
WHILE(@Contador <= @Total)
BEGIN
INSERT INTO dbo.Datas ( Data_Inicio )
SELECT
DATEADD(SECOND, dbo.fncRand(1491696000), '1970-01-01')
FROM
dbo.Datas
SET @Contador += 1
END
Guión para la realización de las pruebas.
-- Funções inline
SELECT DATEDIFF(YEAR, Data_Inicio, GETDATE()) + CASE WHEN (MONTH(Data_Inicio) > MONTH(GETDATE()) OR (MONTH(Data_Inicio) = MONTH(GETDATE()) AND DAY(Data_Inicio) > DAY(GETDATE()))) THEN -1 ELSE 0 END
FROM dbo.Datas
SELECT CAST(DATEDIFF(DAY, Data_Inicio, GETDATE()) / 365.25 AS INT)
FROM dbo.Datas
-- Funções T-SQL UDF
SELECT dbo.fncCalcula_Idade(Data_Inicio, GETDATE())
FROM dbo.Datas
SELECT dbo.fncCalcula_Idade2(Data_Inicio, GETDATE())
FROM dbo.Datas
-- Funções CLR
SELECT CLR.dbo.fncCalcula_Idade(Data_Inicio, GETDATE())
FROM dbo.Datas
SELECT CLR.dbo.fncCalcula_Idade2(Data_Inicio, GETDATE())
FROM dbo.Datas
Como se esperaba, las funciones en línea presentaron el mejor rendimiento, CLR presentó un rendimiento similar y las funciones T-SQL tardaron mucho más que las otras 2 soluciones. Además, la solución con división por 365,25 fue mejor que usar CASE en los 3 escenarios.
¡Eso es todo, amigos!
Espero que hayas aprendido a calcular la edad correctamente y con el mejor rendimiento posible.
Un abrazo y hasta la próxima.

Comentários (0)
Carregando comentários…