How to populate a table with a range of dates? How to populate a table with a range of dates? sql sql

How to populate a table with a range of dates?


Try this:

DROP PROCEDURE IF EXISTS filldates;DELIMITER |CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE)BEGIN  WHILE dateStart <= dateEnd DO    INSERT INTO tablename (_date) VALUES (dateStart);    SET dateStart = date_add(dateStart, INTERVAL 1 DAY);  END WHILE;END;|DELIMITER ;CALL filldates('2011-01-01','2011-12-31');

Here's the SQL Fiddle to play with it: http://sqlfiddle.com/#!2/65d13/1

EDIT (to check if date already exists) as asked by Andrew Fox.

CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE)BEGINDECLARE adate date;    WHILE dateStart <= dateEnd DO        SET adate = (SELECT mydate FROM MyDates WHERE mydate = dateStart);        IF adate IS NULL THEN BEGIN            INSERT INTO MyDates (mydate) VALUES (dateStart);        END; END IF;        SET dateStart = date_add(dateStart, INTERVAL 1 DAY);    END WHILE;END;//

Here's the SQL Fiddle to play with it: http://sqlfiddle.com/#!2/66f86/1


I did not want my SQL query to require external dependencies (needing to have a calendar table, procedure for populating a temporary table with dates, etc.) The original idea for this query came from http://jeffgarretson.wordpress.com/2012/05/04/generating-a-range-of-dates-in-mysql/ which I had slightly optimized for clarity and ease of use.

SELECT (CURDATE() - INTERVAL c.number DAY) AS dateFROM (SELECT singles + tens + hundreds number FROM ( SELECT 0 singlesUNION ALL SELECT   1 UNION ALL SELECT   2 UNION ALL SELECT   3UNION ALL SELECT   4 UNION ALL SELECT   5 UNION ALL SELECT   6UNION ALL SELECT   7 UNION ALL SELECT   8 UNION ALL SELECT   9) singles JOIN (SELECT 0 tensUNION ALL SELECT  10 UNION ALL SELECT  20 UNION ALL SELECT  30UNION ALL SELECT  40 UNION ALL SELECT  50 UNION ALL SELECT  60UNION ALL SELECT  70 UNION ALL SELECT  80 UNION ALL SELECT  90) tens  JOIN (SELECT 0 hundredsUNION ALL SELECT  100 UNION ALL SELECT  200 UNION ALL SELECT  300UNION ALL SELECT  400 UNION ALL SELECT  500 UNION ALL SELECT  600UNION ALL SELECT  700 UNION ALL SELECT  800 UNION ALL SELECT  900) hundredsORDER BY number DESC) c  WHERE c.number BETWEEN 0 and 364

It is simple to optimize and scale this table for other uses. You can easily get rid of the tens and hundreds tables if you only need one week of data.

If you need a larger set of numbers, it is easy to add a thousands table. You only need to copy and paste the table with hundreds and add a zero to 9 numbers.


if you're in a situation like me where procedures are prohibited, and your sql user does not have permissions for insert, therefore insert not allowed, but you want to generate a list of dates in a specific period, say current year to do some aggregation, use this

select * from (select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) gen_date from (select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0, (select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1, (select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2, (select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3, (select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) vwhere gen_date between '2017-01-01' and '2017-12-31'