Trucos para el cálculo de diferencias de fechas en SQL Server

Para calcular la diferencia entre dos fechas en SQL Server usaremos DATEDIFF.

Por ejemplo, para hallar la diferencia entre '2007-05-07' y '2007-05-08' en días tan solo basta ejecutar:

SELECT DATEDIFF(day, '2007-05-07', '2007-05-08');

Resultado:
----------
1 day

Para encontrar el primer y último día de un mes:


SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)--primer dia

SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate()  )+1, 0));--ultimo dia

Encontrar el primer día del año pasado:

SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate() ), 0))

Encontrar el primer lunes del mes:

SELECT DATEADD(wk, DATEDIFF(wk,0, dateadd(dd,6-datepart(DAY,getdate()),getdate())), 0);

Encontrar los años, meses y dias transcurridos entre dos fechas. Por ejemplo, para: 2009/02/02 y 2009/01/08 la respuesta debe ser "1 mes y 6 dias"

Aquí su servidor de Vida Amarilla hizo una función que resuelve el problema:

Para probar:

select dbo.EntreFechasAñoMesDia('02/10/1987','02/02/2011')
 
Resultado:
---------
Pasan 23 años y 4 meses 

Validando el cálculo de fechas en Wolfram|Alpha nos muestra lo mismo:

23 years  4 months

Es Correcto.

Referencia:

1. DATEDIFF (Transact_SQL)
2. Obtener fechas en SQL Server
3. Script EntreFechasAñoMesDia de IISLAS

COMENTARIOS 22 Comentarios

22 comentarios :

  1. hola, muy buen aporte el que comentas, solo quería preguntar algo con respecto al último código que pusiste para calcular año, mes y día... quería saber si esto de igual forma se puede aplicar a MySQL 5.3??? o la variación de dicha función es demasiada...?

    de antemano muchas gracias y disculpad por las molestias, pero soy nuevo en esto...

    ResponderEliminar
  2. como podria desarrollar un calculo de dias vividos en dev c++

    ResponderEliminar
  3. tengo problemas con Epi Data cuando intento que me devuelva una fecha en algunos casos 19 años 6 meses y 36 dias cuando en realidad debiera devolver 19 años 7 meses y 6 dias , como puedo solucionar desde ya gracias

    ResponderEliminar
  4. Yo armé esta forma de conseguir la edad. Si encuentran errores me ayudarían mucho para poder actualizar mi código SQL.

    UPDATE MI_TABLA
    SET
    MI_EDAD =
    CASE
    WHEN DATEPART(MM, FEC_NACIMIENTO) = DATEPART(MM, GETDATE()) AND DATEPART(DD, GETDATE()) >= DATEPART(DD, FEC_NACIMIENTO)
    THEN DATEPART(YY, GETDATE()) - DATEPART(YY,FEC_NACIMIENTO)
    ELSE (DATEPART(YY,GETDATE()) - 1) - (DATEPART(YY, FEC_NACIMIENTO))
    END

    -- Explicación:
    En "WHEN" hago la consulta si el mes de nacimiento es igual al mes actual, luego verifico que el día sea igual o menor(osea dias anteriores) al día actual en curso. Si todo esto es verdadero se imprime en THEN la resta del año actual menos la fecha de nacimiento. Y el ELSE me dice que, si no se cumple nada de ello resto los años y le quito 1.

    Saludos!

    ResponderEliminar
  5. Una forma menos complicada de hacer el calculo de anos, mes y dias transcurrido entre dos fechas es esta, entendiendo que cada cual la pueda adaptar a sus necesidades.

    Declare @fec1 as datetime, @fec2 as datetime,
    @anos as int, @meses as int, @dias as int

    set @fec1 = '20120101'
    set @fec2 = GETDATE();

    set @anos = DATEDIFF(YYYY,@fec1, @fec2)
    set @fec1 = DATEADD(YYYY,@anos, @fec1)
    set @meses = DATEDIFF(mm,@fec1, @fec2)
    set @fec1 = DATEADD(mm,@meses, @fec1)
    set @dias = DATEDIFF(dd,@fec1, @fec2)

    select @anos as anos, @meses as meses, @dias as dias

    ResponderEliminar
    Respuestas
    1. Es la mejor opción que pude comprobar. Gracias por el aporte.

      Eliminar
  6. Si yo quisiera saber el primer miércoles de cada mes, como podría hacerlo?

    ResponderEliminar
  7. Declare @lFec1 as datetime, @lFec2 as datetime

    set @lFec1 = '20030814'
    set @lFec2 = '20090801'

    Declare @anos as int, @meses as int, @dias as int, @ld as datetime

    If @lFec1<@lFec2
    Begin
    set @Anos = datepart(yyyy, @lFec2)- datepart(yyyy,@lFec1)
    set @meses = datepart(mm,@lFec2)- datepart(mm,@lFec1)
    set @Dias = datepart(dd,@lFec2)- datepart(dd,@lFec1)

    If @Dias<0 Begin
    set @meses=@meses -1
    set @ld = dateadd(mm, 1, dateadd(mm,-1,@lFec2))
    set @ld = dateadd(DD,-datepart(dd,@ld),@ld)
    set @Dias = @dias + DATEPART(DD,@ld)
    End

    If @meses<0 Begin
    set @Anos = @Anos -1
    set @meses = 12 + @meses
    End

    select @anos as años, @meses as meses, @dias as dias
    End

    ResponderEliminar
  8. Hola como estas ? mira tengo dos problemas significativos,uso el datediff en una tabla para que me diga cuantos dias paso alguien por una habitacion,el resultado esta bien solo que cuando quiero pasar ese resultado a otra tabla donde hago las liquidaciones correspondientes no me muestra el resultado del datediff de la otra tabla.ya trate con innerjoin y con left join lo que hace que empeoren las cosas ya que no muestra ni una de la sotras consultas de la tabla .
    jeje espero aver sido claro el otro problema lo dejo para despues para no ser tan pesado .
    saludos y gracias desde ya a alguna sugerencia ya que este drama hara que tire este proyecto al tacho de papeles .

    ResponderEliminar
  9. Hola buenas, como puedo colocar la sentencia para que me busque los ultimos 6 meses.

    ResponderEliminar
  10. hola, como puedo obtner la diferencia en dias entre dos fechas sin la funcion datediff que no la soporta la version de mysql

    Gracias

    ResponderEliminar
  11. Estimado muy buenos tus articulos pero: POR DIOS QUITA ESA BARRA DE LA INZQUIERDA (TWIYYER, FACEBOOK, ETC) que es molesta e impide leer bien. por lo demas todo excelente, pero esa barra flotante es muy mala idea.

    ResponderEliminar
  12. Quién me podría ayudar a Conseguir la siguiente consulta:
    Obtener los nombres de la tabla Datos que se ingresaron en la fecha 'X' a la fecha 'Y', pero hay que tener en cuenta que en esa tabla Datos solo existe 1 atributo de Fecha que es de tipo datetime, no hay 2 que digan fecha1 y fecha2... ojo!!! lo necesito en storeprocedure... Les agradecería mucho... A ver quién me ayuda... Muchas bendiciones a todos

    ResponderEliminar
  13. ayudenme como hacer esta operacion en sql acerca de funciones

    Crear una función que calcule la antigüedad de un empleado. (PARAMETRO DE ENTRADA: Fecha de ingreso)

    ResponderEliminar
  14. create PROCEDURE SACADIFEENMESES

    @FECHAACTUAL DATE

    AS

    declare @FechaIngreso AS date,
    @FechaEgreso AS date

    select @FechaEgreso = GETDATE()

    Select
    DATEDIFF(mm, @FECHAACTUAL, @FechaEgreso) AS Meses,
    DATEDIFF(dd, @FECHAACTUAL, @FechaEgreso) AS Dias,
    DATEDIFF(yy, @FECHAACTUAL, @FechaEgreso) AS Años

    ResponderEliminar
  15. Muy buena la función compartida en el truco 3, solo que el encontré un pequeño error y lo comparto para que puedan corregirla.

    La sentencia

    SET @Dias = (DAY(DATEADD(mm,1,CAST(('01/' + STR(@MesInicio) + '/' + STR(@AñoInicio)) AS DATETIME)) - 1 )- @DiaInicio) + @DiaFin

    Debe ser reemplazada por las dos líneas siguientes, previa declaración del a variable @DiaFinMesPrevio en la sección donde se declaran las variables dentro de la función (DECLARE @DiaFinMesPrevio INT)

    SET @DiaFinMesPrevio = DAY(CAST('01/' + STR(@MesFin) + '/' + STR(@AñoInicio) AS DATETIME) - 1)
    SET @Dias = (CASE WHEN @DiaFinMesPrevio > @DiaInicio THEN @DiaFinMesPrevio - @DiaInicio ELSE 0 END) + @DiaFin

    Esta corrección soluciona el problema que se genera cuando la fecha de inicio tiene una cantidad de días mayor a la fecha de fin y la fecha de inicio corresponde a un mes de menos de 31 días. Para ver más claramente el error les recomiendo probar la función original calculando la diferencia entre 30/04/2013 y 31/05/2013 y verán que les da la misma diferencia que la que se obtiene entre 30/04/2013 y 01/06/2013 (en ambos casos la función original arroja una diferencia de “Pasa 1 mes y 1 día”). En cambio sí realizan el cambio descripto arriba la función arrojará una diferencia de “Pasa 1 mes y 1 día” entre las fechas 30/04/2013 y 31/05/2013 y una diferencia de “Pasa 1 mes y 2 días” entre las fechas 30/04/2013 y 01/06/2013.

    Espero que les sea útil mi aporte.

    ResponderEliminar
  16. perdón me dice que el nombre del objeto no es valido

    ResponderEliminar
  17. Excelente correxión, justo estaba probando algo similar. :D

    ResponderEliminar
  18. Muy buena solución para hallar el primer día del mes.

    ResponderEliminar
  19. Gracias, me ha sido muy útil, gracias a sus aportes.

    ResponderEliminar