To pytanie dotyczy odejmowania dni roboczych. Zakładając, że weekend to sobota-niedziela, rozwiązanie możemy napisać w następujący sposób:
Wiemy, że:
- Każdy pełny tydzień ma 5 dni roboczych.
- Zatem
- num_of_weeks =
floor(@num_working_days / 5)
- delta_days =
@num_working_days % 5
- num_of_weeks =
Zatem pierwszym przybliżeniem może być:
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)
Nie będzie to jednak działać w następujących i podobnych przypadkach:
Generalnie nie powiedzie się, jeśli:
WEEKDAY(NOW()) - @num_working_days % 5 < 0
Aby to uwzględnić, należy odjąć dodatkowe 2 dni za każdym razem, gdy ten warunek zostanie spełniony.
- overflow_days =
2 * (WEEKDAY(NOW()) - @num_working_days % 5 < 0)
Tak więc drugie przybliżenie byłoby następujące:
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)
Wreszcie
Będzie to działać tak długo, jak now()
nie jest w week-end
dzień. W takim przypadku musisz zastąpić now()
w powyższym wzorze z datą zakończenia poprzedniego tygodnia:
- weekend_correction =
DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) % 5 DAY)
Co prowadzi do okropnego wyglądu, ale w pełni działającego:
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);
Teraz, w środowisku produkcyjnym, zalecam utworzenie funkcji na serwerze MySQL, która hermetyzuje tę logikę, i można ją wywołać za każdym razem, gdy trzeba odjąć dni robocze.