Reputation: 5038
I'm a beginner in SQL. There are many sources on the internet but I'm not able to achieve this. Let's say I have a row like this:
Date format is 'YYYY-MM-DD':
+---------+--------------+------------+------------+
| name | course | sdate | edate |
+---------+--------------+------------+------------+
| Tanzeel | SQL Bootcamp | 2019-05-28 | 2019-11-20 |
+---------+--------------+------------+------------+
Basically this says Tanzeel was enrolled in SQL Bootcamp from May 2019 to Nov 2019. (Day/Date doesn't matters here). I want to break down this range like this:
+---------+--------------+------------+
| name | course | enrollMonth|
+---------+--------------+------------+
| Tanzeel | SQL Bootcamp | 2019-05 |
+---------+--------------+------------+
| Tanzeel | SQL Bootcamp | 2019-06 |
+---------+--------------+------------+
| Tanzeel | SQL Bootcamp | 2019-07 |
+---------+--------------+------------+
| Tanzeel | SQL Bootcamp | 2019-08 |
+---------+--------------+------------+
| Tanzeel | SQL Bootcamp | 2019-09 |
+---------+--------------+------------+
| Tanzeel | SQL Bootcamp | 2019-10 |
+---------+--------------+------------+
| Tanzeel | SQL Bootcamp | 2019-11 |
+---------+--------------+------------+
What is the correct approach for this. Please help me. My versions are:
+--------------------------+-------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------+
| admin_tls_version | TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 |
| immediate_server_version | 999999 |
| innodb_version | 8.0.21 |
| original_server_version | 999999 |
| protocol_version | 10 |
| slave_type_conversions | |
| tls_version | TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 |
| version | 8.0.21 |
| version_comment | MySQL Community Server - GPL |
| version_compile_machine | x86_64 |
| version_compile_os | Win64 |
| version_compile_zlib | 1.2.11 |
+--------------------------+-------------------------------+
Upvotes: 1
Views: 246
Reputation: 164214
With a recursive CTE
:
with recursive cte as (
select name, course, sdate, edate
from tablename
union all
select name, course, sdate + interval 1 month, edate
from cte
where last_day(sdate) < edate
)
select name, course, date_format(sdate, '%Y-%m') enrollMonth
from cte
See the demo.
Results:
> name | course | enrollMonth
> :------ | :----------- | :----------
> Tanzeel | SQL Bootcamp | 2019-05
> Tanzeel | SQL Bootcamp | 2019-06
> Tanzeel | SQL Bootcamp | 2019-07
> Tanzeel | SQL Bootcamp | 2019-08
> Tanzeel | SQL Bootcamp | 2019-09
> Tanzeel | SQL Bootcamp | 2019-10
> Tanzeel | SQL Bootcamp | 2019-11
Upvotes: 1