Reputation: 3706
With the MySQL WEEK function I can set the first day of the week to Sunday or Monday. But how about if I need to set it to some other day?
The reason for this is that we have clients going through online programs that have a specific "check-in day" each week. For some it will be Monday, for some Tuesday, for some Wednesday and so on, and we need to see the averages of multiple check-ins for each week.
If it was always Sunday and Monday I can do something like this:
SELECT YEAR(timestamp) AS year, WEEK(timestamp,1) AS week ... GROUP BY year, week
But there's thousands of clients and I need to get the weekly averages for each client, but each client will have their own first day of the week — going Monday to Sunday, Wednesday to Tuesday, Saturday to Friday and so on.
Any ideas how we can do this?
Thanks for your help!
Upvotes: 0
Views: 1023
Reputation: 3166
I'm calling your timestamp time
, to not confuse it with a datatype:
CREATE TABLE clientdates(client VARCHAR(20),
time TIMESTAMP)
I suggest you just subtract the DAYOFWEEK("check-in day")
, which you in comments refer to as entry_due_at
from the time. Then you'll get the offset you need for the WEEK()
to work:
SET @client := 'client2';
-- in my example I just picked the first date the client had an entry
SELECT @weekday := DAYOFWEEK(min(time)) - 1 -- need 0 to 6
FROM clientdates
WHERE client = @client;
SELECT client,
@weekday,
YEAR(time) AS year,
WEEK(time - INTERVAL @weekday DAY) AS week_offset,
count(*)
FROM clientdates
WHERE client = @client
GROUP BY client, year, week_offset
Running it with this data, which will have it's first day on a Thursday:
INSERT INTO clientdates
VALUES ('client2', '2021-08-19 04:14:07.9'),
('client2', '2021-08-20 04:14:07.9'),
('client2', '2021-08-21 04:14:07.9'),
('client2', '2021-08-22 04:14:07.9'),
('client2', '2021-08-23 04:14:07.9'),
('client2', '2021-08-24 04:14:07.9'),
('client2', '2021-08-25 04:14:07.9'),
('client2', '2021-08-26 04:14:07.9'),
('client2', '2021-08-27 04:14:07.9'),
('client2', '2021-08-28 04:14:07.9'),
('client2', '2021-08-29 04:14:07.9');
I get this result:
client | @weekday | year | week_offset | count(*) |
---|---|---|---|---|
client2 | 2 | 2021 | 33 | 7 |
client2 | 2 | 2021 | 34 | 4 |
If you need to use WEEK(time, 1)
instead, you'll just need to subtract 2 instead of 1 when getting the value for @weekday
, since you need Monday to have the zero-indexed value instead of Sunday.
Upvotes: 1