Oracle's table server offers a built-in function, TRUNC(timestamp,'DY')
. This function converts any timestamp to midnight on the previous Sunday. What's the best way to do this in MySQL?
Oracle also offers TRUNC(timestamp,'MM')
to convert a timestamp to midnight on the first day of the month in which it occurs. In MySQL, this one is straightforward:
TIMESTAMP(DATE_FORMAT(timestamp, '%Y-%m-01'))
But this DATE_FORMAT
trick won't work for weeks. I'm aware of the WEEK(timestamp)
function, but I really don't want week number within the year; this stuff is for multiyear work.
SQL Server provides a function called DATEPART() , which returns a specified part (year, quarter, month, week, hour, minute, etc.) of a specified date. ORDER BY DATEPART(week, RegistrationDate);
The WEEK() function returns the week number for a given date (a number from 0 to 53).
WEEK() function in MySQL is used to find week number for a given date. If the date is NULL, the WEEK() function will return NULL. Otherwise, it returns the value of week which ranges between 0 to 53. The date or datetime from which we want to extract the week.
You can group month and year with the help of function DATE_FORMAT() in MySQL. The GROUP BY clause is also used.
You can use both YEAR(timestamp)
and WEEK(timestamp)
, and use both of the these expressions in the SELECT
and the GROUP BY
clause.
Not overly elegant, but functional...
And of course you can combine these two date parts in a single expression as well, i.e. something like
SELECT CONCAT(YEAR(timestamp), '/', WEEK(timestamp)), etc... FROM ... WHERE .. GROUP BY CONCAT(YEAR(timestamp), '/', WEEK(timestamp))
Edit: As Martin points out you can also use the YEARWEEK(mysqldatefield)
function, although its output is not as eye friendly as the longer formula above.
Edit 2 [3 1/2 years later!]: YEARWEEK(mysqldatefield)
with the optional second argument (mode
) set to either 0 or 2 is probably the best way to aggregate by complete weeks (i.e. including for weeks which straddle over January 1st), if that is what is desired. The YEAR() / WEEK()
approach initially proposed in this answer has the effect of splitting the aggregated data for such "straddling" weeks in two: one with the former year, one with the new year.
A clean-cut every year, at the cost of having up to two partial weeks, one at either end, is often desired in accounting etc. and for that the YEAR() / WEEK()
approach is better.
Figured it out... it's a little cumbersome, but here it is.
FROM_DAYS(TO_DAYS(TIMESTAMP) -MOD(TO_DAYS(TIMESTAMP) -1, 7))
And, if your business rules say your weeks start on Mondays, change the -1
to -2
.
Edit
Years have gone by and I've finally gotten around to writing this up. https://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With