Group by weekofyear MySQL for the end of the year - mysql

I need stats on orders, week by week, so I have done this:
SELECT YEAR(orders.date), WEEKOFYEAR(orders.date), COUNT(*)
FROM orders
GROUP BY YEAR(orders.date), WEEKOFYEAR(orders.date)
It worked for one year, but just now (new year) it does not count the last days of 53rd week (jan 1st, 2nd, 3rd). How can I update my Query in order to have the full last week (from Monday 2015-12-28 to Sunday 2016-01-03)?

You need to switch to YEARWEEK(orders.date,3) to get the ISO weeks as a single column. Using WEEK(orders.date,3) (which is exactly the same as WEEKOFYEAR) will return the correct week number, but YEAR(orders.date) will return either 2015 or 2016, splitting the week into four days in 2015 and and three days in 2016.

As Strawberry mentioned in the comments you're looking for the WEEK function. I just checked the documentation at the MySQL website.
Week(date [,mode])
This function returns the week number for date. The two-argument form of WEEK() enables you to specify whether the week starts on Sunday or Monday and whether the return value should be in the range from 0 to 53 or from 1 to 53. If the mode argument is omitted, the value of the default_week_format system variable is used
Here's an example
SELECT WEEK('2008-12-31',1);
=> 53
It should also be noted that this is not the same as the WEEKOFYEAR function.
Returns the calendar week of the date as a number in the range from 1 to 53. WEEKOFYEAR() is a compatibility function that is equivalent to WEEK(date,3).
We can see that the value of the mode parameter here is 3. Here is the table that shows the values for the modes
Mode First day of week Range Week 1 is the first week
0 Sunday 0-53 With a Sunday in this year
1 Monday 0-53 With 4 or more days this year
2 Sunday 1-53 With a Sunday in this year
3 Monday 1-53 With 4 or more days this year
4 Sunday 0-53 With a Sunday in this year
5 Monday 0-53 With 4 or more days this year
6 Sunday 1-53 With a Sunday in this year
7 Monday 1-53 With 4 or more days this year
Source
https://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_week

As I understand you, you want calculate total orders for one week only once not twice for various years.
I've written SQL query for SQL Server, but I think you can easy rewrite it on mysql.
DECLARE #test_table TABLE(created_date DATETIME, VALUE INT)
INSERT INTO #test_table
SELECT N'20151231', 10
UNION ALL
SELECT N'20151228', 20
UNION ALL
SELECT N'20160101', 40
UNION ALL
SELECT N'20160104', 5
UNION ALL
SELECT N'20160107', 2
SELECT first_day_week_number,
SUM(value) AS total
FROM
(SELECT *,
DATEPART(ww,
DATEADD(dd, -DATEPART(dw, created_date)+2, created_date)) AS first_day_week_number
FROM #test_table ) AS T
GROUP BY first_day_week_number
To avoid problems with years you could calculate first week day of order date and then get week number from it.

Related

Getting only the data from the first day of the week to the current day of the week

So I want to select all my row that is recorded by this week.
For example. today is January 30 2019, which is Wednesday. I would like to select all my row from Monday(January 28,2019) to Wednesday only(current day). And when tomorrow comes, the rows added on Thursday will also be selected.
This will continue til Sunday. And when the Next week Monday comes, it will only select the rows recorded on that Monday. (February 4, 2019) and so on.
I just need to get the (THIS WEEK) data, not the past 7 days.
I have a dateadded column
-----------------------------
Firstname|Lastname|dateadded
Michael |Jordan |2019-02-03 <-(Feb 3, 2019)
Mark |Perez |2019-01-30
Paul |George |2019-01-28
John |Wayne |2019-01-25
-----------------------------
A query that will only select this weeks added data.
Mark Perez and Paul George which is in the same week of the current day.
select * from names WHERE YEARWEEK(`dateadded`, 1) = YEARWEEK(CURDATE(), 1)
will only select the last 7 days of the curdate.
Well you can use WEEKDAY() to get the day number of the current day within the week, and susbstract if from the current date :
SELECT SUBDATE(CURDATE(), WEEKDAY(CURDATE()))
Yields :
2019-01-28
Demo on DB Fiddle
As commented by Nick, here is an example of a query that uses the above approach to filter a table :
SELECT t.*
FROM test t
WHERE t.idate >= SUBDATE(CURDATE(), WEEKDAY(CURDATE()))
ORDER BY t.idate
Demo on DB Fiddle
You have example of how your table looks?
You could insert records with date and week numbers.
If you record days by week numbers it's easy like :
SELECT * FROM weektable WHERE weekno='5';
.. There are 52 weeks in a year ..
This will select everything from week number 5 and will be adding new rows from same week number automatically.

week number returns previous year last week number for january fist week in mysql

I am facing one issue while fetching the week number for 2016-01-01(fist week) in mysql. it return 53 if i use week() function or weekofyear() function . I have to get as 1 since I am linking the weeknumber in my project in other places and if it returns 1 the next week number also should be adjusted according to that. Kindly any one help me on this.
The manual says:
If the week containing January 1 has 4 or more days in the new year,
it is week 1.
Otherwise, it is the last week of the previous year, and the next week
is week 1.
So you can provide the mode to the week function.
Mode First day of week Range Week 1 is the first week …
0 Sunday 0-53 with a Sunday in this year
1 Monday 0-53 with 4 or more days this year
2 Sunday 1-53 with a Sunday in this year
3 Monday 1-53 with 4 or more days this year
4 Sunday 0-53 with 4 or more days this year
5 Monday 0-53 with a Monday in this year
6 Sunday 1-53 with 4 or more days this year
7 Monday 1-53 with a Monday in this year
Something like this:
select WEEK('2016-01-01',0) + 1;
FIDDLE DEMO

Selecting mysql records for next week

I'm looking for the MySQL query to select date records that fall within the next week using Sunday - Saturday as the format for the week.
So in other words, I'm not looking to get the dates a week from today, I'm looking to get the dates that fall within Sunday - Saturday of the next week.
I found this: MySQL Query to select data from last week? and it works for the previous week from Sunday - Saturday but I'm not sure how to tweak this to get the dates for the next week.
Any ideas?
SELECT * FROM table
WHERE
date > date_add(curdate(),INTERVAL(7-dayofweek(curdate()))DAY)
AND date <= date_add(curdate(),INTERVAL(14- dayofweek(curdate()))DAY)
You can use:
SELECT *
FROM YourTable
WHERE WEEK(YourDateField, 6) = WEEK(CURRENT_DATE + INTERVAL 7 DAY, 6)
for selecting recods of next week (starting with sunday)
Weeks count is 1 to 53 with first week of the year having at least 4 days in the year

MySQL compare by week

I have a select statement of which needs to base its WHERE on a timestamp but for all dates within that week beginning monday.
The MySQL
SELECT DISTINCT(unique_reference) AS unique_reference, date(datetime) AS datetime
FROM sales_tickets
WHERE Date(datetime)='$datetime'
This is based on the fact that $datetime can be any date but the select statement needs to get all records from that week, example: if its the Monday 12th May 2014, it will fetch all results from that week, instead of the one day.
Currently, its fetching only one day of results.
I have no idea how to rectify this issue. Any advise would be awesome thanks.
You can compare using the WEEK function :
WHERE WEEK(DATE(datetime)) = WEEK('$datetime')
If you have multiples years for entries, you can use instead the YEARWEEK function.
Edit for first day of week:
WEEK and YEARWEEK functions have both a second optional argument which tells when a week start. Try to consider mode 1 or 5.
Mode First day of week Range Week 1 is the first week …
0 Sunday 0-53 with a Sunday in this year
1 Monday 0-53 with 4 or more days this year
2 Sunday 1-53 with a Sunday in this year
3 Monday 1-53 with 4 or more days this year
4 Sunday 0-53 with 4 or more days this year
5 Monday 0-53 with a Monday in this year
6 Sunday 1-53 with 4 or more days this year
7 Monday 1-53 with a Monday in this year
A sargable solution would explicitly calculate the start and end points of your desired range:
WHERE datetime >= DATE('$datetime') + INTERVAL 0 - WEEKDAY('$datetime') DAY
AND datetime < DATE('$datetime') + INTERVAL 7 - WEEKDAY('$datetime') DAY
The easiest method might be to have your WHERE statement check against a range of values, which you can calculate beforehand.
I'll assume you're using php.
So your SQL statement will be:
SELECT DISTINCT(unique_reference) AS unique_reference, date(datetime) AS datetime
FROM sales_tickets
WHERE (Date(datetime) > '$startDate')
AND (Date(datetime) < '$endDate');
You'll first have to figure out what $startDate and $endDate are:
$endDate = strtotime('Monday', time()); // might need to adjust this depending on when your week starts
$startDate = $endDate - 7*24*60*60; //one week before.
Be careful with converting times between unix timestamps and datetimes used in SQL, but you get the idea.
Try WEEK():
WHERE WEEK(datetime)=WEEK('$datetime')
Read more: WEEK()

How to group by week in MySQL?

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.
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/
The accepted answer above did not work for me, because it ordered the weeks by alphabetical order, not chronological order:
2012/1
2012/10
2012/11
...
2012/19
2012/2
Here's my solution to count and group by week:
SELECT CONCAT(YEAR(date), '/', WEEK(date)) AS week_name,
YEAR(date), WEEK(date), COUNT(*)
FROM column_name
GROUP BY week_name
ORDER BY YEAR(DATE) ASC, WEEK(date) ASC
Generates:
YEAR/WEEK YEAR WEEK COUNT
2011/51 2011 51 15
2011/52 2011 52 14
2012/1 2012 1 20
2012/2 2012 2 14
2012/3 2012 3 19
2012/4 2012 4 19
You can get the concatenated year and week number (200945) using the YEARWEEK() function. If I understand your goal correctly, that should enable you to group your multi-year data.
If you need the actual timestamp for the start of the week, it's less nice:
DATE_SUB( field, INTERVAL DAYOFWEEK( field ) - 1 DAY )
For monthly ordering, you might consider the LAST_DAY() function - sort would be by last day of the month, but that should be equivalent to sorting by first day of the month ... shouldn't it?
Just ad this in the select :
DATE_FORMAT($yourDate, \'%X %V\') as week
And
group_by(week);
If you need the "week ending" date this will work as well. This will count the number of records for each week. Example: If three work orders were created between (inclusive) 1/2/2010 and 1/8/2010 and 5 were created between (inclusive) 1/9/2010 and 1/16/2010 this would return:
3 1/8/2010
5 1/16/2010
I had to use the extra DATE() function to truncate my datetime field.
SELECT COUNT(*), DATE_ADD( DATE(wo.date_created), INTERVAL (7 - DAYOFWEEK( wo.date_created )) DAY) week_ending
FROM work_order wo
GROUP BY week_ending;
Previous Sunday:
STR_TO_DATE(CONCAT(YEARWEEK(timestamp,2),'0'),'%X%V%w')
Previous Monday:
STR_TO_DATE(CONCAT(YEARWEEK(timestamp,3),'1'),'%x%v%w')
DATE_FORMAT(date,format) reference:
%V - Week (01..53), where Sunday is the first day of the week; WEEK() mode 2; used with %X
%v - Week (01..53), where Monday is the first day of the week; WEEK() mode 3; used with %x
%w - Day of the week (0=Sunday..6=Saturday)
%X - Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
%x - Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
I like the week function in MySQL, but in my situation, I wanted to know which week of the month a row was in. I utlized this solution:
where run_date is a timestamp like 2021-02-25 00:00:00
concat (
date_format(run_date, '%Y-%m'),
' wk ',
(week(run_date,1) - ( week(date_format(run_date, '%Y-%m-01')) - 1))
) as formatted_date
This outputs:
2021-02-23 ---> 2021-02 wk 4
2021-02-25 ---> 2021-02 wk 4
2021-02-11 ---> 2021-02 wk 2
2021-03-02 ---> 2021-03 wk 1
The idea behind this is that I want to know (with relative certainty) which week of the month in question did the date occur?
So we concatenate:
date_format(run_date, '%Y-%m') to get 2021-02
then we add the literal text string wk
then we use:
week(run_date, 1) to get the week (1 to start Monday) of this record, (which would be 7 because 02/21/2021 is in the 7th week of the year, and we subtract whatever the week is on the 1st day of this same month - the week() for 2021-02-01 is 5, because it is in the 5th week of the year:
(week(date_format(run_date, '%Y-%m-01'))
Unfortunately, this will start out the counting at 0, which people don't like, so we subtract 1 from the last part of the concatenation result so that the "week" start at 1.
This may be a good option:
SELECT
year(datetime_field) as year_date, week(datetime_field) as week_date
FROM
bd.table
GROUP BY
year_date, week_date;
It would look like this:
'2020', '14'
'2020', '15'
'2020', '16'
'2020', '17'
'2020', '18'