MySQL的date 数据类支持的时间范围是 1000-1-1 到9999-12-31,通过计算可以知道最大支持天数为3287181天属于百万级别的。
mysql> SELECT DATEDIFF('9999-12-31','1000-01-01') days;
+---------+
| days |
+---------+
| 3287181 |
+---------+
1 row in set (0.28 sec)
为了生产百万数据的日历,我们可以使用如下代码生成日历,当然在实际应用中可能只需要上千或者万条记录就够了(10年也就是3650条数据记录)。
创建一个表存储数字0到9,在创建一个表存储日期,然后通过添加字段扩展显示。
CREATE TABLE if not exists num (i int);
INSERT INTO num (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
CREATE TABLE if not exists calendar(dateseq date);
--自2018-01-01开始生成100万条日历记录:
INSERT INTO calendar(dateseq) SELECT
ADDDATE(
( -- 这里的起始日期,你可以换成当前日期
DATE_FORMAT("2018-1-1", '%Y-%m-%d')
),
numlist.id
) AS `date`
FROM
(
SELECT
n1.i + n10.i * 10 + n100.i * 100 + n1000.i * 1000+ n10000.i * 10000 +n100000.i*100000 AS id
FROM
num n1
CROSS JOIN num AS n10
CROSS JOIN num AS n100
CROSS JOIN num AS n1000
CROSS JOIN num AS n10000
CROSS JOIN num AS n100000
) AS numlist;
Query OK, 1000000 rows affected (16.67 sec)
Records: 1000000 Duplicates: 0 Warnings: 0
耗时16.67s即生成了100万条日历的记录。
mysql> SELECT MIN(dateseq),MAX(dateseq),COUNT(1) FROM calendar;
+--------------+--------------+----------+
| MIN(dateseq) | MAX(dateseq) | COUNT(1) |
+--------------+--------------+----------+
| 2018-01-01 | 4755-11-28 | 1000000 |
+--------------+--------------+----------+
1 row in set (1.02 sec)
有了上面的数据我们可以生成BI报表中经常需要的使用时间维度的表。
CREATE TABLE dim_calendar(
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '自增主键',
dateseq DATE NOT NULL COMMENT '日期序列,格式YYYY-MM-DD',
year_digital INT NOT NULL COMMENT '年份,2018',
quarter_digital TINYINT COMMENT '季度,1--4',
month_digital TINYINT COMMENT '月份,数字月份,1--12',
peroid_date INT COMMENT '日期,20180725',
peroid_month INT COMMENT '月份,201807',
period_week TINYINT COMMENT '一年的中的第几周,1-53',
weekseq TINYINT COMMENT '周几,1-7',
year_day INT COMMENT '一年中的第几天,1--366',
month_day INT COMMENT '当月的第几天 ,1-31'
)
COMMENT '日历维度表';
利用上面的的日历表可以生成时间维度表的数据:
--插入数据:
INSERT INTO dim_calendar(dateseq,year_digital,quarter_digital,month_digital,peroid_date,peroid_month,period_week,weekseq,year_day,month_day)
SELECT
dateseq,YEAR(dateseq),QUARTER(dateseq),MONTH(dateseq),DATE_FORMAT(dateseq,'%Y%m%d'),DATE_FORMAT(dateseq,'%Y%m'),WEEKOFYEAR(dateseq),DAYOFWEEK(dateseq)-1,DAYOFYEAR(dateseq),DAYOFMONTH(dateseq)
FROM calendar;
--查询验证:
mysql> select * from dim_calendar where dateseq='2018-07-25'\G
*************************** 1. row ***************************
id: 206
dateseq: 2018-07-25
year_digital: 2018
quarter_digital: 3
month_digital: 7
peroid_date: 20180725
peroid_month: 201807
period_week: 30
weekseq: 3
year_day: 206
month_day: 25
1 row in set (0.00 sec)