none
Como obtener la cantidad de días en sql, entre un rango de fechas? RRS feed

  • Pregunta

  • Hola, 

    Quiero obtener en sql los días que esta trabajando un empleado y los días que esta descansando, para esto el empleado tiene asignada una Jornada de trabajo que es 2x1 trabaja 2 días y descansa 1 día, esta jornada da inicio cuando firma contrato y en la tabla esta registrado con el campo de Jornada_Ini y Jornada_Fin(Cuando terminas de Laborar).

    Muestro imagen de como esta la tabla calendario


    Tengo al Empleado que inicia a trabajar el día 10 de Marzo y finaliza el 11 de Marzo por lo cual el día 12 debe de ser su descanso, e iniciar nuevamente su jornada de trabajo que seria el día 13 y 14 trabajados y el día 15 descansado así hasta terminar el año o su contrato.

    lo que quiero hacer es obtener los días que labora y los días que descansa de acuerdo a las fechas seleccionadas en una pantalla y poder ver el reporte 

    Tengo lo siguiente:

    DECLARE @FechaDesde datetime, @FechaHasta datetime
    set @FechaDesde='2015-03-10 00:00:00.000'
    set @FechaHasta='2015-03-31 00:00:00.000'
    SELECT CC.NumOperador,
    j.Descripcion as Jornada,
    (DATEDIFF(DAY, MAX(@FechaDesde), MAX(@FechaHasta)) + 1) AS DíasTrabajados
    FROM Operadores O
    JOIN Jornada J ON O.cveJornada = J.cveJornada
    JOIN Calendario CC ON O.NumOperador = CC.NumOperador
    WHERE O.cveTipoOperador = 2 
    AND O.NumOperador = 900200
    GROUP BY  j.Descripcion, cc.NumOperador

    y con ello obtengo que trabaja 22 días

    pero me falta quitar los días de descanso que son obligatorios en su Jornada Laboral

    entonces debería de obtener 15 días Trabajados y 7 Descansados.

    alguna idea de como puedo lograrlo tomando en cuenta siempre la Fecha de Inicio de Jornada y las Fecha desde y Fecha hasta para obtener el reporte.


    Molitaa

    miércoles, 12 de abril de 2017 17:43

Respuestas

  • ¿No te parece raro que no recibas respuestas?

    Me parece muy confuso la tabla que muestras, ¿para un empleado defines una jornada de un día donde suceden eventos en días posteriores? no le encuentro sentido a la lectura de la tabla. La fecha que tú seleccionas ¿es de la jornada o el de las incidencias?. Creo que el problema no es lo que requieres -que lo has repetido varias veces y se entiende- el problema es que los datos no tienen forma, pienso yo. Sin embargo pueda que sea yo el del problema, el que no entiende, espero puedas recibir ayuda adicional.

    jueves, 20 de abril de 2017 3:47

Todas las respuestas

  • molitaa,

    Si la relación es 3 a 1 entonces creo que basta con:

    SELECT DiasTrabajados/3 AS [Descanso],
    DiasTrabajados - DiasTrabajados/3 AS [Trabajado]


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    miércoles, 12 de abril de 2017 18:06
  • Gracias Willams, como me comentas obtengo el resultado correcto, 

    Te comento esto lo obtengo con las Fechas ingresadas en mi pantalla 

    Y revisando la pantalla de Ingreso de contrato que es el día 10 es correcto:


    ahí puedo ver que los que están en color Verde contando el Rojo porque ese aun no se lo voy a descontar (es una falta) el resultado es 15 días trabajados y 7 descansados, pero que pasa si mi Fecha de Ingreso fuera el día 8 de Marzo y en mi pantalla de generar el reporte yo solicito el reporte del día 10 al día 31 de marzo sin contar la fecha de ingreso que sería día 8 que es cuando inicia la Jornada de su contrato.


    entonces ahí serían 14 días trabajados, ahí no cuento la falta (ya que esta en día de descanso laboral quedo así porque modifique las fechas para poder explicarme un poquito) y sería 8 descansados.

    Que puedo hacer para tomar en cuenta mi Jornada_Ini y poder obtener el resultado como esta en el calendario.

    Espero a verme explicado!!



    Molitaa


    • Editado molitaa miércoles, 19 de abril de 2017 14:38 para poder subir más imagenes
    miércoles, 12 de abril de 2017 19:47
  • Saludos:

    Me parece que no se puede hacer en un simple select.

    Lo ideal seria:

    1) Tomar el numero de dias seleccionados.

    2) A este resultado, hacer la progresion de cada dos dias de trabajo, añadir uno de trabajo.

    3) Sumar las variables.

    Ejemplo para empezar:

    DECLARE @FechaDesde datetime, @FechaHasta datetime
    DECLARE @TotalDias, @Trabajados, @Descanso
    
    set @FechaDesde='2015-03-10 00:00:00.000'
    set @FechaHasta='2015-03-31 00:00:00.000'
    
    SET @TotalDias = DATEDIFF(DAY, MAX(@FechaDesde), MAX(@FechaHasta)) + 1
    
    WHILE @TotalDias > 0
       SET @Trabajados + 2
       SET @Descanso + 1
       SET @TotalDias - 2
    END
    
    SELECT CC.NumOperador,
    j.Descripcion as Jornada, @TotalDias AS DíasTrabajados, @Trabajados, @Descanso
    FROM Operadores O
    JOIN Jornada J ON O.cveJornada = J.cveJornada
    JOIN Calendario CC ON O.NumOperador = CC.NumOperador
    WHERE O.cveTipoOperador = 2 
    AND O.NumOperador = 900200
    GROUP BY  j.Descripcion, cc.NumOperador

    Hace falta validar los totales, sumas, restas y otras cosas, pero creo que te da una idea.

    Espero ayude.

    JOSE LUIS


    Dios NO los llamo LAS DIEZ RECOMENDACIONES

    jueves, 13 de abril de 2017 19:09
  • DECLARE @Jornana_Ini datetime

    SELECT @Jornada_Ini = Jornada_Ini FROM Operador WHERE Codigo =900200

    --Una vez teniendo la Jornada Inicial esto me servira para ver si al fecha que ingresas como FechaDesde es una fecha de trabajo o de descanso para el operador

    SELECET @DiasDiferencia=DATEDIFF(DAY,@Jornada_Ini ,@FechaDesde)

    ---Esto es para ver si la division es entero o float, si es entero el primer dia es de descanso

    IF (FLOAT)@DiasDiferencia+1/3 - @DiasDiferencia+1/3 ==0

    THEN

    SELECT DiasTrabajados/3+1 AS [Descanso],
    DiasTrabajados - DiasTrabajados/3+1 AS [Trabajado]

    ELSE

    THEN

    SELECT DiasTrabajados/3 AS [Descanso],
    DiasTrabajados - DiasTrabajados/3 AS [Trabajado]

    Espero te sirva, me dejas saber!!

    viernes, 14 de abril de 2017 21:14
  • ...Pero que pasa si mi Fecha de Ingreso fuera el día 8 de Marzo y en mi pantalla de generar el reporte yo solicito el reporte del día 10 al día 31 de marzo sin contar la fecha de ingreso que sería día 8 que es cuando inicia la Jornada de su contrato.

    Nada complicado, calcula el siguiente día de inicio de jornada a partir del día de la fecha de inicio del reporte, a partir de ese día calcula los días utilizando la relación 3:1 y restando -de ser necesario- los días no laborados. No ensayo algo de código porque desconozco las tablas y columnas que intervienen en el proceso, pero no es para nada complicado. Si tienes dudas adjunta en sentencias CREATE e INSERT las tablas y datos de prueba -únicamente lo relevante- para que podamos escribir las instrucciones necesarias, ayúdanos a tener el escenario de pruebas.


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    • Propuesto como respuesta Joyce_ACModerator lunes, 17 de abril de 2017 15:42
    • Votado como útil molitaa lunes, 17 de abril de 2017 16:15
    domingo, 16 de abril de 2017 23:39
  • hola Willams, 

    te comparto la tabla de Calendario que es en donde registro la fecha de inicio de Jornada, como puedes ver es la misma siempre pero tengo una cveincidencia con fecha inicial y final esto es por si tiene alguna falta, permiso u otro detalle que no se presente a laborar con esto no hay problema, pero te comento para que te des una idea el porque se registra nuevamente la Jornada Inicial y final.

    como puedo obtener lo que me mencionas con la relación 3:1


    Molitaa

    lunes, 17 de abril de 2017 16:06
  • Hola Raul, 

    Gracias por el apoyo, te comento utilice lo que me indicaste quedando de la siguiente manera:

    DECLARE @FechaDesde datetime, @FechaHasta datetime, @numOperador int, @Jornada nvarchar (10),  @DiasTrabajados int
    declare @DiasDiferencia as FLOAT, @Descanso int, @Trabajo int
    set @FechaDesde='2017-03-08 00:00:00.000'
    set @FechaHasta='2017-03-31 00:00:00.000'
    SELECT @numOperador= CC.NumOperador,
    @Jornada =j.Descripcion,
    @DiasTrabajados= (DATEDIFF(DAY, MAX(@FechaDesde), MAX(@FechaHasta)) + 1),  
    @DiasDiferencia= abs(DATEDIFF(DAY,Jornada_Ini ,@FechaDesde)) 
    FROM trkOperadores O
    JOIN trkJornada J ON O.cveJornada = J.cveJornada
    JOIN CopCalendario CC ON O.NumOperador = CC.NumOperador
    WHERE O.cveTipoOperador = 2 
    AND O.NumOperador = 900200
    GROUP BY  j.Descripcion, cc.NumOperador, Jornada_Ini

    IF (@DiasDiferencia+1/3) - (@DiasDiferencia+1/3) =0
    SELECT @Descanso =(@DiasTrabajados/3) ,--AS [Descanso],
    @Trabajo =@DiasTrabajados - (@DiasTrabajados/3) --AS [Trabajado]
    ELSE
    SELECT @Descanso= (@DiasTrabajados/3),  -- AS [Descanso],
    @Trabajo =@DiasTrabajados - (@DiasTrabajados/3) --AS [Trabajado]

    select @numOperador as NumOperador, @Jornada as Jornada, @DiasTrabajados as DiasTrabajados, 
    @Descanso as Descanso, @Trabajo as Trabajo

    me regreso lo que esperaba, pero si yo quiero agregara para empleados que tiene una Jornada de 8x2 Trabajan 8 días y descansan 2 donde lo puedo agregar para obtener igual días descansados y días trabajados en las fechas mencionadas


    Molitaa

    lunes, 17 de abril de 2017 21:29
  • alguna idea más que me pueda ser de ayuda?

    Gracias


    Molitaa

    martes, 18 de abril de 2017 16:21
  • ...alguna idea más que me pueda ser de ayuda?

    Llevas 6 días sin resolver el problema que al parecer es simple, yo te reitero mi recomendación: "...adjunta en sentencias CREATE e INSERT las tablas y datos de prueba -únicamente lo relevante- para que podamos escribir las instrucciones necesarias, ayúdanos a tener el escenario de pruebas".

    Los que apoyamos en el foro compartimos tiempo de nuestras labores del día a día, si nos facilitas las cosas y eres puntual en lo que requieres obtendrás respuestas con cierta brevedad, de lo contrario el post tendrá días sin ser respondido o por lo menos no con propuestas concretas y exactas según requieres.

    Fíjate el enlace adjunto, el usuario postea sus tablas y nos deja datos de prueba y además nos deja claramente los resultados que espera:

    Sugerencia de forma de realizar el requerimiento


    martes, 18 de abril de 2017 21:53
  • Estimado que bien que te haya servido , para lo que tú indicas podrías tratar la siguiente lógica:

    2x1 ---> 2 días laborados y uno de descanso --->2/1 +1 =3

    8x2 ---> 8 días laborados y dos de descanso --->8/2 +1 =5

    Este ultimo valor sería que lo captures en una variable en mi ejemplo @NuevaVariable y lo reemplazes en la la lógica de tu TSQL:

    DECLARE @FechaDesde datetime, @FechaHasta datetime, @numOperador int, @Jornada nvarchar (10),  @DiasTrabajados int
    declare @DiasDiferencia as FLOAT, @Descanso int, @Trabajo int
    set @FechaDesde='2017-03-08 00:00:00.000'
    set @FechaHasta='2017-03-31 00:00:00.000'
    SELECT @numOperador= CC.NumOperador,
    @Jornada =j.Descripcion,
    @DiasTrabajados= (DATEDIFF(DAY, MAX(@FechaDesde), MAX(@FechaHasta)) + 1),  
    @DiasDiferencia= abs(DATEDIFF(DAY,Jornada_Ini ,@FechaDesde)) 
    FROM trkOperadores O
    JOIN trkJornada J ON O.cveJornada = J.cveJornada
    JOIN CopCalendario CC ON O.NumOperador = CC.NumOperador
    WHERE O.cveTipoOperador = 2 
    AND O.NumOperador = 900200
    GROUP BY  j.Descripcion, cc.NumOperador, Jornada_Ini
    
    IF (@DiasDiferencia+1/3) - (@DiasDiferencia+1/@NuevaVariable) =0
    SELECT @Descanso =(@DiasTrabajados/@NuevaVariable) ,--AS [Descanso],
    @Trabajo =@DiasTrabajados - (@DiasTrabajados/@NuevaVariable) --AS [Trabajado]
    ELSE
    SELECT @Descanso= (@DiasTrabajados/@NuevaVariable),  -- AS [Descanso],
    @Trabajo =@DiasTrabajados - (@DiasTrabajados/@NuevaVariable) --AS [Trabajado]
    
    select @numOperador as NumOperador, @Jornada as Jornada, @DiasTrabajados as DiasTrabajados, 
    @Descanso as Descanso, @Trabajo as Trabajo


    Me dejas saber si te funciono 

    Saludos!!!

    martes, 18 de abril de 2017 22:24
  • Gracias por tus comentarios Willams y más por el Ejemplo,

    Comparto lo que tengo espero poder explicarme.

    Tengo la Tabla Calendario la cual se utilizara como Tabla Informativa Numero de Operador cuando Inicia su Jornada y Cuando debe de Terminar, así como las Incidencias que pueden irse presentando (Faltas, Vacaciones U Otros) con el Inicio y Final de la Incidencia:

    CREATE TABLE Calendario(
    	idNumOperador int IDENTITY(1,1),
    	NumOperador int, 
    	Jornada_Ini datetime,
    	Jornada_Fin datetime,
    	cveIncidencia int ,
    	Fecha_Ini datetime ,
    	Fecha_Fin datetime 
    	)

    Puedo insertar los Valores en la Tabla directo, o bien desde la pantalla de c# Ejemplo:

    INSERT INTO Calendario VALUES(900200,'2017-03-08 00:00:00.000','2017-03-09 00:00:00.000',12,'2017-04-19 00:00:00.000','2017-04-19 00:00:00.000')
    
    

    Como pueden ver las Jornada_Ini y Jornada_Fin no cambian siempre serán las misas, lo que cambiara son el tiempo de Incidencia que se tenga al igual que sus Fechas.

    Les comparto la Imagen de la Tabla con la información:


    El Resultado que espero es el numero del Operador con el total de días desde la FechaDesde hasta la FechaHasta que envío de mi pantalla c# y obtener los días que laboro dentro de esas Fechas restando sus descansos que tiene obligatorios, pero tomando en cuenta la Fecha del Inicio de la Jornada.

    Recordando que este Operador tiene una Jornada de 2x1 Trabaja 2 días y Descansa 1.

    Espero a verme explicado.

    Gracias


    Molitaa

    miércoles, 19 de abril de 2017 14:46
  • ¿No te parece raro que no recibas respuestas?

    Me parece muy confuso la tabla que muestras, ¿para un empleado defines una jornada de un día donde suceden eventos en días posteriores? no le encuentro sentido a la lectura de la tabla. La fecha que tú seleccionas ¿es de la jornada o el de las incidencias?. Creo que el problema no es lo que requieres -que lo has repetido varias veces y se entiende- el problema es que los datos no tienen forma, pienso yo. Sin embargo pueda que sea yo el del problema, el que no entiende, espero puedas recibir ayuda adicional.

    jueves, 20 de abril de 2017 3:47