Esta pergunta é sobre a subtração de dias úteis. Assumindo que o fim de semana é sábado-domingo, podemos escrever a solução da seguinte forma:
Sabemos que:
- Toda semana inteira tem 5 dias úteis.
- Assim,
- num_of_weeks =
floor(@num_working_days / 5)
- delta_days =
@num_working_days % 5
- num_of_weeks =
Assim, uma primeira aproximação poderia 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)
No entanto, isso não funcionará nos seguintes casos e em casos semelhantes:
Geralmente, ele falhará se:
WEEKDAY(NOW()) - @num_working_days % 5 < 0
Para compensar isso, um adicional de 2 dias deve ser subtraído sempre que essa condição for atendida.
- overflow_days =
2 * (WEEKDAY(NOW()) - @num_working_days % 5 < 0)
Então, a segunda aproximação seria:
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,
Isso funcionará enquanto
now()
não está em um week-end
dia. Nesse caso, você precisaria substituir now()
na fórmula acima com a data de término da semana anterior:- weekend_correction =
DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) % 5 DAY)
O que leva à aparência horrível, mas totalmente 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);
Agora, em produção, recomendo que você crie uma função em seu servidor MySQL para encapsular essa lógica, e você pode chamar essa função sempre que precisar subtrair dias úteis.