如何用一系列date填充表格?
我需要一个MySQL表来保存2011-01-01和2011-12-31之间的所有date。 我创build了一个列名为“_date”的表,inputDATE。
用什么查询我可以用所有期望的date填充表(而不是必须手动input)?
尝试这个:
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');
这是SQL小提琴与它一起玩: http ://sqlfiddle.com/#!2/65d13/1
编辑(检查date是否已经存在),如安德鲁福克斯所要求的。
CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE) BEGIN DECLARE 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;//
这里是SQL小提琴与它一起玩: http ://sqlfiddle.com/#!2/66f86/1
我不希望我的SQL查询需要外部依赖关系(需要有日历表,用于填充date的临时表的过程等)。此查询的原始思路来自http://jeffgarretson.wordpress.com/2012 / 05/04 /生成一个范围的date在MySQL /我已经稍微优化,清晰和易用性。
SELECT (CURDATE() - INTERVAL c.number DAY) AS date FROM (SELECT singles + tens + hundreds number FROM ( SELECT 0 singles 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 ) singles JOIN (SELECT 0 tens UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60 UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90 ) tens JOIN (SELECT 0 hundreds UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300 UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600 UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900 ) hundreds ORDER BY number DESC) c WHERE c.number BETWEEN 0 and 364
为了其他用途优化和缩放这个表格很简单。 如果你只需要一个星期的数据,你可以很容易地摆脱数十和数百个表。
如果你需要一个更大的数字集合,很容易添加一个数千个表格。 您只需要复制和粘贴数百个表,并添加一个零到九个数字。
我发现这个粘贴并去的变种工作:
DROP PROCEDURE IF EXISTS FillCalendar; DROP TABLE IF EXISTS calendar; CREATE TABLE IF NOT EXISTS calendar(calendar_date DATE NOT NULL PRIMARY KEY); DELIMITER $$ CREATE PROCEDURE FillCalendar(start_date DATE, end_date DATE) BEGIN DECLARE crt_date DATE; SET crt_date = start_date; WHILE crt_date <= end_date DO INSERT IGNORE INTO calendar VALUES(crt_date); SET crt_date = ADDDATE(crt_date, INTERVAL 1 DAY); END WHILE; END$$ DELIMITER ; CALL FillCalendar('2013-01-01', '2013-01-03'); CALL FillCalendar('2013-01-01', '2013-01-07');
如果你有一个足够大的连续ID的桌子,你可以使用 –
INSERT INTO tablename (_date) SELECT '2011-01-01' + INTERVAL (id - 1) DAY FROM some_table_with_lots_of_ids WHERE id BETWEEN 1 AND 365
请注意:但请注意,这可能会让你在闰年遇到麻烦(有366天)
感谢IvanD。 我有一个更好的解决scheme,允许你创build一个指定的日历表。 例如,如果我试图创build一个2014-04的表,它看起来像这样:
SELECT (CURDATE() - INTERVAL c.number DAY) AS DATE FROM ( SELECT singles + tens + hundreds number FROM ( SELECT 0 singles 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 ) singles JOIN ( SELECT 0 tens UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60 UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90 ) tens JOIN ( SELECT 0 hundreds UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300 UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600 UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900 ) hundreds ORDER BY number DESC ) c WHERE c.number BETWEEN DAYOFYEAR(NOW()) - DAYOFYEAR('2014-04-01')- DAY(LAST_DAY('2014-04-01')) +1 AND DAYOFYEAR(NOW()) - DAYOFYEAR('2014-04-01')
这可以通过使用简单的for循环在PHP中实现。 有几种方法可以做到这一点。 一种方法是将原始date放置在一个variables中,并通过在每个循环中添加+1天来让循环遍历每一个循环,例如,您将从01/01/2011开始,然后循环将会第一次加0,下一天加1,然后加2天等等,直到$ ivariables。 然后,您可以打印出date或将其添加到数据库中。 在这种情况下,$ i代表以0为起点的计数器,<= 365是您想要经过多less个循环,等于或less于天数,$ i ++将$ ivariables加1在每个循环。
date('Ymd')将date转换为yyyy-mm-dd。使用大写字母Y给出一个完整的4位数年份,而使用小写字母y将给出该年份的最后2位数字。为了将其添加到MySQL中的date字段。
strtotime($ originalDate将dateparsing为Unix时间戳,并且。“+”。$ i。“day”)基本上将天数$ i的值添加到date中。
最后是mysqli查询。 $ db表示数据库连接variables,这将需要更改为您为连接设置的任何variables。 接下来是实际的查询。 只要将表格名称和VALUES前面的date换成你的date行名称,你就可以开始了。
以下是一个例子:
<?php for($i=0;$i<=365;$i++){ $originalDate = "01/01/2011"; $date = date('Ym-d',strtotime($originalDate . "+".$i." day")); mysqli_query($db, "INSERT INTO table (date)VALUES('$date')"); }
使用for函数实现这一点的另一种方法是将行为date直接包含在行为中作为与计数器variables的对立,这是更短的一段代码。 用开始date点代替$ i = 0(开始计数点),接着用小于或等于结束date点(循环数),然后用你的加号+1加上第一个语句放到variables准备好使用。
最后,将date转换为Ymd格式,准备放入数据库并运行查询。
与第一个例子一样,这可以被打印或直接放置到数据库中。
以下是一个例子:
<?php for ($startdate = strtotime("2011-01-01"); $startdate <= strtotime("2011-12-31"); $startdate = strtotime("+1 day", $startdate)) { $date= date("Ymd", $startdate); mysqli_query($db, "INSERT INTO tracking (date)VALUES('$date')"); }
我听起来可能已经让人感到困惑了,但是希望至less能让你知道它是如何工作的。
受到IvanD大量join的启发,我来到这里:
SELECT DATE_ADD('2015-10-21', INTERVAL c.number DAY) AS DATE FROM ( SELECT singles + tens + hundreds+thousands number FROM ( SELECT 0 singles 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 ) singles JOIN ( SELECT 0 tens UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60 UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90 ) tens JOIN ( SELECT 0 hundreds UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300 UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600 UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900 ) hundreds JOIN ( SELECT 0 thousands UNION ALL SELECT 1000 UNION ALL SELECT 2000 UNION ALL SELECT 3000 UNION ALL SELECT 4000 UNION ALL SELECT 5000 UNION ALL SELECT 6000 UNION ALL SELECT 7000 UNION ALL SELECT 8000 UNION ALL SELECT 9000 ) thousands ORDER BY number DESC ) c WHERE c.number BETWEEN 0 AND DATEDIFF('2016-10-08', '2015-10-21')
如果你在像我这样的情况下, 程序被禁止 ,并且你的sql用户没有权限插入,所以插入不允许 ,但是你想在特定的时间段内生成一个date列表 ,比如当年要做一些聚合,使用这个
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) v where gen_date between '2017-01-01' and '2017-12-31'