none
Diferencia de días, sin contar fines de semanas ni días festivos RRS feed

  • Pregunta

  • Como le puedo hacer para sacar la diferencia de 2 fechas sin que me cuente fines de semana ni días festivos. Todo en sql. Esta es mi tabla:

    FechaAlta-FechaAceptacion=FechaDiferencia

    lunes, 11 de marzo de 2019 23:33

Todas las respuestas

  • Hola Silvia Valdespino:

    Los días festivos, es algo, que ni los humanos somos capaces de discernir, por tanto SQL Server en modo automático, lo tiene complicado.

    Puedes crear una tabla tipo calendario, donde introduces los fines de semana (esto es fácil automatizarlo), y los festivos (esto depende de demasiados factores).

    Te expongo una posible solución.

    -- Itzik's VATN
    CREATE FUNCTION [dbo].[ufn_GetNums](@low AS bigint, @high AS bigint) 
    RETURNS table
    AS
    RETURN (
    WITH
    L0 AS (SELECT c FROM (VALUES(1),(1)) AS D(c)),
    L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
    L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
    L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
    L4 AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
    L5 AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
    Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum FROM L5)
    SELECT TOP(@high - @low + 1) @low + rownum - 1 AS n
    FROM Nums
    ORDER BY rownum
    );
    go
    

    Crea esta función que te dará un rango de números, entre lo @low y @high

    CREATE TABLE CALENDARIO (ID INT IDENTITY(1,1), FECHA DATE, TIPO VARCHAR(2))
    GO
    

    Creas una tabla calendario, que puedes mejorar.

    DECLARE @table TABLE(fecha DATE);
    INSERT INTO @table(fecha)
    VALUES('20170101');
    
    INSERT INTO CALENDARIO 
    SELECT DATEADD(day, o.n, fecha), 'FS'
    FROM @table
         CROSS APPLY dbo.[ufn_GetNums](1, 3650) AS o
    WHERE DATEPART(WEEKDAY, DATEADD(day, o.n, fecha)) BETWEEN 6 AND 7;
    
    GO

    Llenamos el calendario con los fines de semana que hay en 10 años desde el siguiente al 1 de enero de 2017. El rango lo establece ufn_getNums(1, xxxx)

    Con los dias de fin de semana ya cubiertos, introduce tus festivos. simplemente insertando en calendario, y marcando otro tipo.

    Tu escenario

    DECLARE @TABLE TABLE (FECHAALTA DATETIME, FECHAACEPTACION DATETIME)
    INSERT INTO @TABLE (FECHAALTA, FECHAACEPTACION)
    VALUES
    ('20171121 15:12:32','20171127 02:23:31'),
    ('20171117 13:24:58','20171123 16:32:47'),
    ('20171116 09:57:06','20171127 12:28:57'),
    ('20171117 16:38:04','20171122 12:36:01');
    
    /* Tu escenario */
    select t.FECHAACEPTACION, t.FECHAALTA, DATEDIFF(DAY,T.FECHAALTA,T.FECHAACEPTACION)-c.diasNoLaborales AS DIF
    From
        @TABLE T
        cross apply
        (
        select count(*) as diasNoLaborales
        from calendario as c
        where 
    			c.fecha >= cast(T.fechaalta as date) 
    		and c.fecha <= cast(T.fechaaceptacion as date) 
    		and c.TIPO = 'FS'
        ) as c; 
    

    Cuentas en c los dias que hay en calendario entre estas fechas y se lo restas a la diferencia de dias entre fecha de alta y fecha de aceptacion.

    Salida:

    Espero te ayude

    • Propuesto como respuesta Pedro Alfaro martes, 12 de marzo de 2019 15:41
    • Votado como útil Pedro Alfaro viernes, 15 de marzo de 2019 15:44
    martes, 12 de marzo de 2019 5:55
  • Aprovechando el hilo, ¿como se puede calcular tiempo transcurrido entre dos campos fechas sin importar asuetos pero detallando por ejemplo 29 años, 10 meses, y 13 días?
    miércoles, 13 de marzo de 2019 0:32
  • Hola JoséMiel:

    Como los hilos no son caros, quizá era mejor, que lo preguntases en otro.

    No obstante, una posible solución la tienes en este hilo

    declare @fechainicio datetime = '20190312';
    declare @fechaFin datetime = '20190313'
    declare @fechaDiferencia as datetime = @fechaFin - @fechaInicio 
    declare @difSegundos as bigint = DATEDIFF( SECOND, @fechaInicio, @fechaFin )
    
    
     select @fechaInicio as fechaInicio, @fechaFin as fechaFin
    , @fechaDiferencia as fechaResultado
    --tiempo transcurrido en años, meses, días y en horas:minutos:segundos
    , DATEDIFF( YEAR, '19000101', @fechaDiferencia ) as anios
    , MONTH( @fechaDiferencia ) -1 as meses
    , DAY( @fechaDiferencia ) -1 as dias
    , CAST( @fechaDiferencia AS TIME ) as tiempo

    https://social.msdn.microsoft.com/Forums/es-ES/c3830d57-7943-4172-816d-2852dc48a22b/como-obtener-el-tiempo-transcurrido-de-varias-fechas-horas-de-inicio-y-fechas-horas-fin-y-sumar-los?forum=sqlserveres

    • Propuesto como respuesta Pedro Alfaro viernes, 15 de marzo de 2019 15:44
    miércoles, 13 de marzo de 2019 5:25
  • Ya lo revise funciona bien con algunas correcciones pero la idea me funciono muy bien 
    jueves, 14 de marzo de 2019 19:48
  • Como le puedo hacer para que me calcule con horas?
    martes, 19 de marzo de 2019 19:28