Generate dynamic table of all months between two dates
P粉663883862
P粉663883862 2023-08-28 12:44:46
0
2
577
<p>I have a table that looks like this: </p> <table class="s-table"> <thead> <tr> <th>Name</th> <th>INT_VALUE</th> <th>Start</th> <th>END</th> </tr> </thead> <tbody> <tr> <td>a</td> <td>100</td> <td>2013-11-16</td> <td>2014-11-16</td> </tr> </tbody> </table> <p>The goal is to output the following: </p> <table class="s-table"> <thead> <tr> <th>Name</th> <th>INT_VALUE</th> <th>Start</th> <th>END</th> <th>interval</th> </tr> </thead> <tbody> <tr> <td>a</td> <td>100</td> <td>2013-11-16</td> <td>2014-11-16</td> <td>11-2013</td> </tr> <tr> <td>a</td> <td>100</td> <td>2013-11-16</td> <td>2014-11-16</td> <td>December 2013</td> </tr> <tr> <td>a</td> <td>100</td> <td>2013-11-16</td> <td>2014-11-16</td> <td>1-2014</td> </tr> <tr> <td>a</td> <td>100</td> <td>2013-11-16</td> <td>2014-11-16</td> <td>February 2014</td> </tr> </tbody> </table> <p>I've started using this. But I'm not sure how to use the START and END dates in the table to determine the start and end of the list of months between calculations. </p> <pre class="brush:php;toolbar:false;">SELECT START, calendar, COUNT(1) FROM table1 AS t1 RIGHT JOIN (SELECT row_number() OVER (ORDER BY SEQ4()) AS MONTHS , TO_DATE(DATEADD(MONTH, MONTHS, '2019-05-01')) AS calendar FROM TABLE(GENERATOR(rowcount=>80))) ON t1.START = calendar GROUP BY 1, 2 ORDER BY 2, 1 ;</pre> <p>The goal here is to associate an int value with each month between the start and end of the range. </p>
P粉663883862
P粉663883862

reply all(2)
P粉924915787

Moved the number range into its own CTE to separate things, we now have a large list of 80 numbers (probably larger).

Then we find the number of months between start/end and concatenate the same number of rows. Then do the math to convert the range into a selection:

WITH range_of_numbers AS (
    SELECT 
        row_number() OVER (ORDER BY SEQ4())-1 AS rn
    FROM TABLE(GENERATOR(rowcount=>80))
)
SELECT 
    t1.name, 
    t1.int_value, 
    t1.start,
    t1.end,
    DATEADD(MONTH, r.rn, t1.start) as interval
FROM table1 AS t1
JOIN range_of_numbers as r
    ON date_diff('month', t1.START, t1.end) <= between r.rn
ORDER BY 2,1,3;

Another option is to build a long range date table

CREATE TABLE dates AS 
SELECT 
     DATEADD(MONTH, row_number() OVER (ORDER BY SEQ4())-1, '1980-01-01') as month_date
FROM TABLE(GENERATOR(rowcount=>8000))

Then we use BETWEEN to get the included values ​​in the (start, end) range, which becomes:

FROM table1 AS t1
JOIN dates as d
    ON d.month_date BETWEEN t1.START AND t1.end
P粉567112391
WITH RECURSIVE
cte AS ( SELECT name, int_value, start, `end`, 
                1 rownum, DATE_FORMAT(start, '%m-%Y') `interval`
         FROM source_table
         UNION ALL
         SELECT name, int_value, start, `end`, 
                1 + rownum, DATE_FORMAT(start + INTERVAL rownum MONTH, '%m-%Y')
         FROM cte
         WHERE start + INTERVAL rownum - 1 MONTH < `end` )
         
SELECT name, int_value, start, `end`, `interval`
FROM cte
ORDER BY rownum;

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=bdd028a7755fdcb8296df2301baeb295

If you don't want the month to have leading zeros, use the '%c-%Y' pattern.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template