Saltar al contenido

Función MySQL para encontrar el número de días hábiles entre dos fechas

Posterior a buscar en diferentes repositorios y páginas al final hemos hallado la resolución que te mostramos a continuación.

Solución:

Esta expresión –

5 * (DATEDIFF(@E, @S) DIV 7) + MID('0123444401233334012222340111123400012345001234550', 7 * WEEKDAY(@S) + WEEKDAY(@E) + 1, 1)

calcula el número de días hábiles entre la fecha de inicio @S y la fecha de finalización @E.

Supone que la fecha de finalización (@E) no es anterior a la fecha de inicio (@S). Compatible con DATEDIFF en el sentido de que la misma fecha de inicio y finalización da cero días hábiles. Ignora las vacaciones.

los string de dígitos se construye de la siguiente manera. Cree una tabla de días de inicio y de finalización, las filas deben comenzar con el lunes (DÍA DE LA SEMANA 0) y las columnas también deben comenzar con el lunes. Rellene la diagonal de arriba a la izquierda a abajo a la derecha con todos los 0 (es decir, hay 0 días hábiles entre lunes y lunes, martes y martes, etc.). Para cada día, comience en la diagonal (siempre debe ser 0) y complete las columnas a la derecha, un día a la vez. Si aterriza en una columna de día de fin de semana (día no laborable), el número de días laborables no cambia, se lleva desde la izquierda. En caso contrario, el número de días hábiles aumenta en uno. Cuando llegue al final de la fila, vuelva al inicio de la misma fila y continúe hasta que alcance la diagonal nuevamente. Luego pasa a la siguiente fila.

Por ejemplo, suponiendo que el sábado y el domingo no sean días hábiles,

 | M T W T F S S
-|--------------
M| 0 1 2 3 4 4 4
T| 4 0 1 2 3 3 3
W| 3 4 0 1 2 2 2
T| 2 3 4 0 1 1 1
F| 1 2 3 4 0 0 0
S| 1 2 3 4 5 0 0
S| 1 2 3 4 5 5 0

Luego concatene los 49 valores en la tabla en el string.

Por favor, hágamelo saber si encuentra algún error.

-Editar tabla mejorada:

 | M T W T F S S
-|--------------
M| 0 1 2 3 4 4 4
T| 4 0 1 2 3 3 3
W| 3 4 0 1 2 2 2
T| 2 3 4 0 1 1 1
F| 1 2 3 4 0 0 0
S| 0 1 2 3 4 0 0
S| 0 1 2 3 4 4 0

mejorado string: ‘0123444401233334012222340111123400001234000123440’

expresión mejorada:

5 * (DATEDIFF(@E, @S) DIV 7) + MID('0123444401233334012222340111123400001234000123440', 7 * WEEKDAY(@S) + WEEKDAY(@E) + 1, 1)

Esta solución utiliza básicamente el mismo enfoque que la de Rodger, excepto que el método para generar la matriz es mucho más complejo. Nota: Esta salida de esta solución no es compatible con NETWORKDAYS.

Al igual que en la solución de Rodger, calcula el número de días hábiles entre la fecha de inicio (@S) y la fecha de finalización (@E) sin tener que definir un procedimiento almacenado. Se supone que la fecha de finalización no es anterior a la fecha de inicio. El uso de la misma fecha de inicio y finalización producirá 0. Los días festivos no se tienen en cuenta.

La principal diferencia entre esta solución y la de Rodger es que la matriz y la resultante string de dígitos está construido por un algoritmo complejo que no he incluido. La salida de este algoritmo se valida mediante una prueba unitaria (consulte las entradas y salidas de prueba a continuación). En la matriz, la intersección de cualquier par de valores de x e y dado (DÍA DE LA SEMANA(@S) y DÍA DE LA SEMANA(@E) produce la diferencia en días laborables entre los dos valores. El orden de asignación en realidad no es importante ya que los dos se suman para trazar la posición.

Los días hábiles son de lunes a viernes.

 | M T W T F S S
-|--------------
M| 0 1 2 3 4 5 5
T| 5 0 1 2 3 4 4
W| 4 5 0 1 2 3 3
T| 3 4 5 0 1 2 2
F| 2 3 4 5 0 1 1
S| 0 1 2 3 4 0 0
S| 0 1 2 3 4 5 0

Los 49 valores de la tabla se concatenan en los siguientes string:

0123455501234445012333450122234501101234000123450

Al final, la expresión correcta es:

5 * (DATEDIFF(@E, @S) DIV 7) + MID('0123455501234445012333450122234501101234000123450', 7 * WEEKDAY(@S) + WEEKDAY(@E) + 1, 1)

He verificado las siguientes entradas y salidas usando esta solución:

Sunday, 2012-08-26 -> Monday, 2012-08-27 = 0
Sunday, 2012-08-26 -> Sunday, 2012-09-02 = 5
Monday, 2012-08-27 -> Tuesday, 2012-08-28 = 1
Monday, 2012-08-27 -> Monday, 2012-09-10 = 10
Monday, 2012-08-27 -> Monday, 2012-09-17 = 15
Monday, 2012-08-27 -> Tuesday, 2012-09-18 = 16
Monday, 2012-08-27 -> Monday, 2012-09-24 = 20
Monday, 2012-08-27 -> Monday, 2012-10-01 = 25
Tuesday, 2012-08-28 -> Wednesday, 2012-08-29 = 1
Wednesday, 2012-08-29 -> Thursday, 2012-08-30 = 1
Thursday, 2012-08-30 -> Friday, 2012-08-31 = 1
Friday, 2012-08-31 -> Saturday, 2012-09-01 = 1
Saturday, 2012-09-01 -> Sunday, 2012-09-02 = 0
Sunday, 2012-09-02 -> Monday, 2012-09-03 = 0
Monday, 2012-09-03 -> Tuesday, 2012-09-04 = 1
Tuesday, 2012-09-04 -> Wednesday, 2012-09-05 = 1
Wednesday, 2012-09-05 -> Thursday, 2012-09-06 = 1
Thursday, 2012-09-06 -> Friday, 2012-09-07 = 1
Friday, 2012-09-07 -> Saturday, 2012-09-08 = 1
Saturday, 2012-09-08 -> Sunday, 2012-09-09 = 0
Monday, 2012-09-24 -> Sunday, 2012-10-07 = 10
Saturday, 2012-08-25 -> Saturday, 2012-08-25 = 0
Saturday, 2012-08-25 -> Sunday, 2012-08-26 = 0
Saturday, 2012-08-25 -> Monday, 2012-08-27 = 0
Saturday, 2012-08-25 -> Tuesday, 2012-08-28 = 1
Saturday, 2012-08-25 -> Wednesday, 2012-08-29 = 2
Saturday, 2012-08-25 -> Thursday, 2012-08-30 = 3
Saturday, 2012-08-25 -> Friday, 2012-08-31 = 4
Saturday, 2012-08-25 -> Sunday, 2012-09-02 = 0
Monday, 2012-08-27 -> Monday, 2012-08-27 = 0
Monday, 2012-08-27 -> Tuesday, 2012-08-28 = 1
Monday, 2012-08-27 -> Wednesday, 2012-08-29 = 2
Monday, 2012-08-27 -> Thursday, 2012-08-30 = 3
Monday, 2012-08-27 -> Friday, 2012-08-31 = 4
Monday, 2012-08-27 -> Saturday, 2012-09-01 = 5
Monday, 2012-08-27 -> Sunday, 2012-09-02 = 5

¿Podrían estar equivocadas las cadenas propuestas?

DATEDIFF(desde, hasta) excluye ‘hasta’. De la misma manera también debería esto string:

lunes -> viernes = lunes, martes, miércoles, jueves = 4

lunes -> sábado = lunes, martes, miércoles, jueves, viernes = 5

Martes -> Lunes = Tu, Wed, Th, Vie, omitir el sábado, omitir el domingo, se excluye el lunes = 4

y así

Matriz propuesta:

 | M T W T F S S
-|--------------
M| 0 1 2 3 4 5 5
T| 4 0 1 2 3 4 4
W| 3 4 0 1 2 3 3
T| 2 3 4 0 1 2 2
F| 1 2 3 4 0 1 1
S| 0 1 2 3 4 0 0
S| 0 1 2 3 4 5 0

Cadena: ‘0123455401234434012332340122123401101234000123450’

¿Me estoy perdiendo de algo? 🙂

Sección de Reseñas y Valoraciones

Si te sientes suscitado, eres capaz de dejar un escrito acerca de qué te ha gustado de esta división.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *