Function for week of the month in mysql
AFAIK, there is no standard on the first week of month.
First week of year is the week containing
How do you define first week of month?
You'll need to rewrite your query like this:
SELECT WEEK(dateField, 5) - WEEK(DATE_SUB(dateField, INTERVAL DAYOFMONTH(dateField) - 1 DAY), 5) + 1
so that the year transitions are handled correctly, and the weeks start on
Otherwise, your query is fine.
There is an alternative that's sometimes used in reporting databases. It's to create a table, let's call it ALMANAC, that has one row per date (the key), and has every needed attribute of the date that might be useful for reporting purposes.
In addition to the week of the month column, there could be a column for whether or not the date is a company holiday, and things like that. If your company had a fiscal year that starts in July or some other month, you could include the fiscal year, fiscal month, fiscal week, etc. that each date belongs to.
Then you write one program to populate this table out of thin air, given a range of dates to populate. You include all the crazy calendar calculations just once in this program.
Then, when you need to know the attribute for a date in some other table, you just do a join, and use the column. Yes, it's one more join. And no, this table isn't normalized. But it's still good design for certain very specific needs.
(Just to clarify for future readers: this answer to this old question was added because of a bounty that implied the current answer wasn't satisfying, so I added this solution/definition with additional "configuration options" for all kinds of situations.)
There is no standard definition for the
Week of month, but a general solution would be the following formula, that you can configurate to your needs:
select (dayofmonth(dateField) + 6 + (7 - "min_days_for_partial_week") - (weekday(datefield) - "weekday_startofweek" + 7) MOD 7) DIV 7 as week_of_month;
"weekday_startofweek"has to be replaced by the weekday that you want to be the first day of the week (
0 = Monday,
6 = Sunday).
"min_days_for_partial_week"is the number of days the first week has to have to count as week 1 (values
7). Common values will be
1(the first day of the month is always week 1),
4(this would be similar to "iso week of the year", where the first week of the year is the week that contains the thursday, so has at least 4 days), and
7(week 1 is the first complete week).
This formula will return values
0 means that the current week is a partial week that doesn't have enough days to count as week 1, and
6 can only happen when you allow partial weeks with less than 3 days to be week 1.
If your first day of the week is Monday (
"weekday_startofweek" = 0) and week 1 should always be a whole week (
"min_days_for_partial_week" = 7), this will simplify to
select (dayofmonth(dateField) + 6 - weekday(datefield)) DIV 7 as week_of_month;
2016-06-02 you will get
0, because June 2016 started with a Wednesday and for
2016-06-06 you will get
1, since this is the first Monday in June 2016.
To emulate your formula, where the first day of the week is always week 1 (
"min_days_for_partial_week" = 1), and the week starts with Sunday (
"weekday_startofweek" = 6), this will be
select (dayofmonth(dateField) + 12 - (weekday(datefield) + 1) MOD 7) DIV 7 as week_of_month;
Although you might want to comment that properly to know in 2 years where your constants came from.