sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo se excluyen los fines de semana de un date_sub?

Esta pregunta es sobre la resta de días laborables. Suponiendo que el fin de semana es de sábado a domingo, podemos escribir la solución de la siguiente manera:

Sabemos que:

  • Cada semana completa tiene 5 días hábiles.
  • Por lo tanto,
    • num_of_weeks =floor(@num_working_days / 5)
    • delta_days =@num_working_days % 5

Entonces, una primera aproximación podría ser:

SET @num_working_days = 4; -- pick any integer
SET @num_days = 7 * FLOOR(@num_working_days / 5) - @num_working_days % 5;     
SELECT DATE_SUB(NOW(), INTERVAL @num_days DAY)

Sin embargo, esto no funcionará en los siguientes casos y similares:

Generalmente, fallará si:

WEEKDAY(NOW()) - @num_working_days % 5 < 0

Para contabilizar eso, se deben restar 2 días adicionales siempre que se cumpla esta condición.

  • overflow_days =2 * (WEEKDAY(NOW()) - @num_working_days % 5 < 0)

Entonces, la segunda aproximación sería:

SET @num_working_days = 4;
SET @overflow_days = 2 * (WEEKDAY(NOW()) - @num_working_days % 5 < 0)
SET @num_days = 7 * FLOOR(@num_working_days / 5) - @num_working_days % 5;

SELECT DATE_SUB(NOW(), INTERVAL @num_days DAY)

Finalmente,

Esto funcionará siempre que now() no está en un week-end día. En ese caso, deberá reemplazar now() en la fórmula anterior con la fecha de finalización de la semana anterior:

  • weekend_correction =DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) % 5 DAY)

Lo que lleva a la apariencia horrible pero completamente funcional:

SET @num_working_days = 4;
SET @weekend_correction = DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) % 5 DAY);
SET @overflow_days = 2 * (WEEKDAY(@weekend_correction) - @num_working_days % 5 < 0);
SET @num_days = 7 * FLOOR(@num_working_days / 5) - @num_working_days % 5;

SELECT DATE_SUB(@weekend_correction, INTERVAL @num_days DAY); 

Ahora, en producción, le recomiendo que cree una función en su servidor MySQL para encapsular esta lógica, y puede llamar a esta función siempre que necesite restar días hábiles.