For the purpose of example we use static @start
and @end
dates, but in practice you can replace them with your column names and all of these values will be recalculated per-row.
SET @start = '2012-09-30';
SET @end = '2012-11-03';
SELECT
@raw_days := DATEDIFF(@end, @start)+1 'raw_days',
@full_weeks := FLOOR(@raw_days / 7) 'full_weeks',
@odd_days := @raw_days - @full_weeks * 7 'odd_days',
@wday_start := DAYOFWEEK(@start) 'wday_start',
@wday_end := DAYOFWEEK(@end) 'wday_end',
@weekend_intrusion := @wday_start + @odd_days 'weekend_intrusion',
@extra_weekends :=
IF(@wday_start = 1, IF(@odd_days = 0, 0, 1),
IF(@weekend_intrusion > 7, 2,
IF(@weekend_intrusion > 6, 1, 0)
)
) 'extra_weekends',
@total_weekends := @full_weeks * 2 + @extra_weekends 'total_weekends',
@total_workdays := @raw_days - @total_weekends 'total_workdays'
The IF
statements boil down to:
If the week starts on a Sunday, and there are no 'odd' days, then there are no extra weekend days. If there are odd days, then there can only be 1 weekend day since it can't possibly stretch to Saturday since that would be a 'full' week.
Otherwise, we see if the remaining portion of a week extends past Sunday. If so, add 2 weekend days. Else if the portion goes to Saturday, add 1 weekend day. Else 0.
Output:
+----------+------------+----------+------------+----------+-------------------+----------------+----------------+----------------+
| raw_days | full_weeks | odd_days | wday_start | wday_end | weekend_intrusion | extra_weekends | total_weekends | total_workdays |
+----------+------------+----------+------------+----------+-------------------+----------------+----------------+----------------+
| 34 | 4 | 6 | 1 | 6 | 7 | 1 | 9 | 25 |
+----------+------------+----------+------------+----------+-------------------+----------------+----------------+----------------+