Convert Month into weeks in MySQL - mysql

I am looking to breakdown a Month into weeks(starting Monday) in MySQL.
For example,
Sept 3 - 9th
Sept 10 - 16th
How to achieve this using MySql?
Thanks in advance.

This query will produce the results you want. It generates a table of possible week numbers in the month (0 to 4) using a UNION, and then it adds those week numbers to the computation of the first Monday of the month (stored in the variable #firstday which is JOINed to the table of week numbers).
SELECT #firstday + INTERVAL w WEEK AS start, #firstday + INTERVAL w WEEK + INTERVAL 6 DAY AS end
FROM (SELECT 0 AS w UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) weeks
JOIN (SELECT #firstday := FROM_DAYS(TO_DAYS(CURDATE())-DAY(CURDATE())+1) +
(7 - WEEKDAY(FROM_DAYS(TO_DAYS(CURDATE())-DAY(CURDATE())+1))) % 7) f
HAVING end <= LAST_DAY(#firstday)
Output:
start end
2018-09-03 2018-09-09
2018-09-10 2018-09-16
2018-09-17 2018-09-23
2018-09-24 2018-09-30
To run the query for any given month, replace CURDATE() in the computation of #firstday (4 places) with a date in the month you are interested in e.g.
SELECT #firstday + INTERVAL w WEEK AS start, #firstday + INTERVAL w WEEK + INTERVAL 6 DAY AS end
FROM (SELECT 0 AS w UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) weeks
JOIN (SELECT #firstday := FROM_DAYS(TO_DAYS('2018-01-20')-DAY('2018-01-20')+1) +
(7 - WEEKDAY(FROM_DAYS(TO_DAYS('2018-01-20')-DAY('2018-01-20')+1))) % 7) f
HAVING end <= LAST_DAY(#firstday)
Output:
start end
2018-01-01 2018-01-07
2018-01-08 2018-01-14
2018-01-15 2018-01-21
2018-01-22 2018-01-28
If you have the flexibility of setting variables, you can clean up the query like so:
SET #day = '2018-01-20';
SET #firstday := FROM_DAYS(TO_DAYS(#day)-DAY(#day)+1) + (7 - WEEKDAY(FROM_DAYS(TO_DAYS(#day)-DAY(#day)+1))) % 7;
SELECT #firstday + INTERVAL w WEEK AS start, #firstday + INTERVAL w WEEK + INTERVAL 6 DAY AS end
FROM (SELECT 0 AS w UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) weeks
HAVING end <= LAST_DAY(#firstday)

You can use function week(date) - https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_week

Related

How to split a date range into chunks of 3 days using MySQL

I am trying to split a specific date range into chunks of 3 days to find the number of records per each three day chunks.
For example, assume I have this table:
User
Minimum Date
Maximum Date
Consecutive Days
1
09/20/2021
09/29/2021
10
And I want to produce this table:
User
Minimum Date
Maximum Date
1
09/20/2021
09/22/2021
1
09/23/2021
09/25/2021
1
09/26/2021
09/28/2021
The reason I ended it off there is because the remaining days are not enough to make up 3 days.
You need in something like
WITH RECURSIVE
cte AS (
SELECT User,
MinimumDate,
MinimumDate + INTERVAL 2 DAY MaximumDate, -- N-1
MaximumDate FinalDate
FROM sourcetable
WHERE MinimumDate + INTERVAL 2 DAY <= MaximumDate -- N-1
UNION ALL
SELECT User,
MinimumDate + INTERVAL 3 DAY, -- N
MinimumDate + INTERVAL 5 DAY, -- 2*N-1
FinalDate
FROM cte
WHERE MinimumDate + INTERVAL 5 DAY <= FinalDate -- 2*N-1
)
SELECT User,
MinimumDate,
MaximumDate
FROM cte
ORDER BY 1, 2;
or (not tested)
WITH RECURSIVE
cte1 AS ( SELECT (MAX(DATEDIFF(MaximumDate, MinimumDate)) DIV 3) - 1 maxrange
FROM sourcetable ),
cte2 AS ( SELECT 0 num
UNION ALL
SELECT num + 1 FROM cte2 WHERE num < maxrange )
SELECT User,
MinimumDate + INTERVAL 3 * num DAY MinimumDate,
MinimumDate + INTERVAL 2 + 3 * num DAY MaximumDate
FROM sourcetable
JOIN cte2 ON MinimumDate + INTERVAL 3 * num DAY <= MaximumDate
ORDER by 1,2

How to query months and number of days in a month of current year in SQL?

I need a table of 2 columns and 12 rows as a result of MySQL/SQL query:
First column is 12 months of the current year.
Second column is the number of days in each month.
Table should look similar to:
months days
January 31
February 28
... ...
December 31
I tried:
DELIMITER $$
DROP PROCEDURE IF EXISTS my_loop$$
CREATE PROCEDURE my_loop()
BEGIN
DECLARE x INT;
SET x = 1;
WHILE x <= 12 DO
SELECT monthname(SUBDATE("2019-12-01", INTERVAL x month)) as months, day(LAST_DAY(SUBDATE("2019-12-01", INTERVAL x month))) as days;
SET x = x + 1;
END WHILE;
END$$
DELIMITER ;
call my_loop();
But it prints out only the first iteration:
months days
January 31
How can I solve this with or without an iteration?
You can do this with a query:
select monthname(makedate(year(curdate()), 1) + interval (x.mon - 1) month) as month_name,
day(last_day(makedate(year(curdate()), 1) + interval (x.mon - 1) month)) as days_in_month
from (select 1 as mon union all select 2 union all select 3 union all select 4 union all
select 5 as mon union all select 6 union all select 7 union all select 8 union all
select 9 as mon union all select 10 union all select 11 union all select 12
) x
order by x.mon;
Here is a db<>fiddle.

MySQL stored procedure, while loop, union dataset

I'm new to stored procedures so I may be doing this wrong. I've created a stored procedure that brings back month name, month start and month end but I'm getting 12 separate datasets.
How can I combine this into one?
BEGIN
SET #i = 0;
SET #start_date = "2018-09-01";
SET #end_date = LAST_DAY('2018-09-01');
WHILE #i < 12 DO
SELECT MONTHNAME(#start_date) AS month, #start_date, #end_date;
SET #i = #i + 1;
SET #start_date = DATE_ADD(#start_date, INTERVAL 1 MONTH);
SET #end_date = LAST_DAY(DATE_ADD(#end_date, INTERVAL 1 MONTH));
END WHILE;
END
You don't need a stored procedure for that.
set #start_date = '2018-09-01';
with recursive months(m) as (
select 0
union all
select m + 1
from months
where m < 11
)
select #start_date + interval m.m month as first_day
, last_day(#start_date + interval m.m month) as last_day
from months m
order by m.m asc
Result:
first_day last_day
2018-09-01 2018-09-30
2018-10-01 2018-10-31
2018-11-01 2018-11-30
2018-12-01 2018-12-31
2019-01-01 2019-01-31
2019-02-01 2019-02-28
2019-03-01 2019-03-31
2019-04-01 2019-04-30
2019-05-01 2019-05-31
2019-06-01 2019-06-30
2019-07-01 2019-07-31
2019-08-01 2019-08-31
But you can ofcourse use that query in your SP too.
Rewrote #Paul Spiegel query so that I can understand how recursive queries work.
SET #start = "2018-09-01";
WITH RECURSIVE months (m)
AS (
SELECT 0
UNION ALL
SELECT m + 1
FROM months
WHERE m < 12
)
SELECT
MONTHNAME(DATE_ADD(#start, INTERVAL m MONTH)) AS month_name,
CONCAT(DATE_ADD(#start, INTERVAL m MONTH), " 00:00:00") AS start_of_month,
CONCAT(LAST_DAY(DATE_ADD(#start, INTERVAL m MONTH)), " 23:59:59") AS end_of_month
FROM months;
For MySQL versions before 8.0 , we can do something like this:
SELECT MONTHNAME(d.dt + INTERVAL i.n MONTH) AS month
, d.dt + INTERVAL i.n MONTH AS start_date
, LAST_DAY(d.dt + INTERVAL i.n MONTH) AS end_date
FROM ( SELECT '2018-09-01' + INTERVAL 0 MONTH AS dt ) d
CROSS
JOIN ( SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
) i
ORDER
BY i.n

how to get next three business days by mysql (current data and next three days)

I want to get the three working days from the current date as excluding Saturday and Sunday. can any one help me out here.
I have tried the interval method and DayOfWeek(day) <> 1 AND DayOfWeek(day) <> 7 but it is not giving me the proper result
Not very elegant but
select d
from
(
select curdate() as d
union all
select curdate() + interval 1 day
union all
select curdate() + interval 2 day
union all
select curdate() + interval 3 day
union all
select curdate() + interval 4 day
) tmp
where dayofweek(d) not in (1,7)
order by d
limit 3

Get Date with Day of Week, Week Number, Month and Year

There some kind to get the Date if you have only the Day of Week, Week number, Month and Year with MySQL?
Example:
I Want to know which day is with this parameters:
Year : 2014
Month : Setember (09)
Week number of Year : 37 OR Week number in Setember : 3
Day of Week: Thursday
The Answer is '2014-09-18'
Using Barmars suggestion you can build a calendar of the year on the fly and check it against your constraints about that:
SET #year := 2014; -- set the year of the constraints
SET #week := 37; -- the week
SET #day_of_week := 5; -- the day of the week (numerical)
-- build the first of the wanted year as supposed by Barmar
SET #first_of_year = STR_TO_DATE(CONCAT(#year, '-01-01'), '%Y-%m-%d');
SELECT
#first_of_year + INTERVAL t.n DAY the_date
FROM (
SELECT
a.N + b.N * 10 + c.N * 100 AS n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) c
ORDER BY n
) t
WHERE
t.n < TIMESTAMPDIFF(DAY, #first_of_year, #first_of_year + INTERVAL 1 YEAR)
AND
WEEK(#first_of_year + INTERVAL t.n DAY) = #week
AND
DAYOFWEEK(#first_of_year + INTERVAL t.n DAY) = #day_of_week
;
Demo
Note
The UNION generates the numbers from 0 to 399, so we can generate a calendar of the year. Now we can apply your other constraints like week in year and day of week.
I asked the same question in portuguese Stake Overflow, and they found a simple solution.
Using str_to_date, year, week number and day of week.
%Y Year, numeric, four digits
%U Week (00..53), where Sunday is the first day of the week
%W Weekday name (Sunday..Saturday)
SELECT str_to_date('201437 Thursday', '%Y%U %W');
Result:
2014-09-18 00:00:00
Portuguese Stack Overflow Answer Link : https://pt.stackoverflow.com/questions/33046/obter-data-com-dia-da-semana-n%C3%BAmero-da-semana-m%C3%AAs-e-ano/33063#33063
Thanks to everyone who helped me