mysql 8.0 日期维度表生成(可运行)
mysql 8.0 日期维度表生成(可运行)
文章目录
- mysql 8.0 日期维度表生成(可运行)
- 日期维度表左右
- 日期维度表生成
- 技术点
日期维度表左右
在数据仓库(Data Warehouse)中,日期维度表(Date Dimension Table)是非常重要的,因为大多数业务数据都涉及时间维度。日期维度表提供了丰富的日期信息,帮助用户进行时间相关的数据分析和报表生成。具体作用包括:
- 提供标准化的日期信息
日期维度表为每个日期提供了标准化的、多种格式的日期表示,如短日期、中日期、长日期、完整日期等。这些格式可以满足不同的业务需求,使得在数据展示时更加灵活。
- 支持多种时间粒度的分析
日期维度表提供了丰富的时间粒度信息,例如:
年、月、季度、周等字段,可以方便地进行按年、按月、按季度或按周的分析。
一年中的第几天(day_in_year)、一月中的第几天(day_in_month)、周的第一天或最后一天等字段,支持更细致的时间计算和汇总分析。
- 支持日期的国际化
通过存储英文和中文等不同语言的日期格式和星期几、月份的名称,日期维度表可以适应国际化需求,支持多语言环境下的数据展示和分析。
- 支持复杂的时间维度计算
日期维度表预先计算了一些复杂的时间逻辑,如:
周的第一天和最后一天(is_first_day_in_week 和 is_last_day_in_week),方便做周度数据分析。
月份和季度的起止日期(is_first_day_in_month、is_last_day_in_month),帮助识别月度或季度的起止时间。
季度编号和年度季度(quarter_number、year_quarter),可以简化季度分析时的逻辑。
- 增强查询效率
通过使用日期维度表,数据仓库中的事实表可以使用日期维度表的主键(日期键 date_key)进行关联,从而减少在查询中对时间的复杂计算。例如,避免在每次查询时都使用 DATE_FORMAT 函数转换日期,而是直接关联维度表中的现成字段,提升查询效率。
- 方便时间序列分析
日期维度表可以帮助快速进行时间序列分析,如趋势分析、环比分析、同比分析等。它为每个日期提供了连续的时间线,方便与事实表关联进行时间序列计算。
- 支持特殊日的标记
日期维度表还可以扩展,加入一些自定义的特殊日标记,如节假日(元旦、春节等)或其他业务相关的重要日期,这样在分析时可以轻松区分平日和特殊日的业务表现。
- 作为业务时间轴的基础
日期维度表通常作为其他维度表的基础,比如根据日期维度表中的季度信息生成季度维度表,根据月份生成月份维度表等。它是建立时间相关的业务逻辑的核心。
- 统一时间标准
通过使用统一的日期维度表,数据仓库中的所有时间相关分析都可以基于同一日期集合,确保一致性。例如,所有按周、月或季度的分析,都可以从同一维度表中获取相关信息,避免由于日期计算的不同而导致的不一致性。
- 易于维护和扩展
日期维度表通常是自动生成的,维护简单。如果需要扩展新的时间字段(如农历日期或其他时区的日期信息),也可以在日期维度表中直接扩展字段,保持数据仓库的灵活性。
日期维度表生成
创建日期维度表的表结构:
CREATE TABLE `dim_date` (
`date` date NOT NULL COMMENT '完整日期 (作为主键)',
`date_short` varchar(10) DEFAULT NULL COMMENT '短日期格式 (YY/MM/DD)',
`date_medium` varchar(12) DEFAULT NULL COMMENT '中日期格式 (MMM DD, YYYY)',
`date_long` varchar(20) DEFAULT NULL COMMENT ' 长日期格式 (MMMM DD, YYYY)',
`date_full` varchar(30) DEFAULT NULL COMMENT ' 完整日期格式 (Weekday, Month DD, YYYY)',
`day_in_year` int DEFAULT NULL COMMENT ' 一年中的第几天',
`day_in_month` int DEFAULT NULL COMMENT ' 一月中的第几天',
`day_name` varchar(10) DEFAULT NULL COMMENT ' 完整的星期几名称 (e.g., Monday)',
`day_abbreviation` varchar(3) DEFAULT NULL COMMENT ' 星期几缩写 (e.g., Mon)',
`day_abbreviation_zh` varchar(6) DEFAULT NULL COMMENT ' 星期几缩写 (e.g., 星期一,星期二)',
`week_in_year` int DEFAULT NULL COMMENT ' 一年中的第几周',
`week_in_month` int DEFAULT NULL COMMENT ' 一月中的第几周',
`month_number` int DEFAULT NULL COMMENT ' 月份编号 (1-12)',
`month_abbreviation` varchar(3) DEFAULT NULL COMMENT ' 月份缩写 (e.g., Jan)',
`month_abbreviation_zh` varchar(3) DEFAULT NULL COMMENT ' 月份缩写 (e.g., 一月,二月)',
`year2` varchar(2) DEFAULT NULL COMMENT ' 2位年份 (e.g., 23)',
`year4` varchar(4) DEFAULT NULL COMMENT ' 4位年份 (e.g., 2023)',
`quarter_name` varchar(6) DEFAULT NULL COMMENT ' 季度名称 (e.g., Q1)',
`quarter_name_zh` varchar(6) DEFAULT NULL COMMENT ' 季度名称 (e.g., 第一季度,第二季度)',
`quarter_number` int DEFAULT NULL COMMENT ' 季度编号 (1-4)',
`is_first_day_in_week` tinyint(1) DEFAULT NULL COMMENT ' 是否为一周的第一天',
`is_last_day_in_week` tinyint(1) DEFAULT NULL COMMENT ' 是否为一周的最后一天',
`is_first_day_in_month` tinyint(1) DEFAULT NULL COMMENT ' 是否为一个月的第一天',
`is_last_day_in_month` tinyint(1) DEFAULT NULL COMMENT ' 是否为一个月的最后一天',
`year_quarter` varchar(7) DEFAULT NULL COMMENT ' 年度季度 (e.g., 2023-Q1)',
`year_month_number` varchar(7) DEFAULT NULL COMMENT ' 年度月份编号 (e.g., 2023-01)',
`year_month_abbreviation` varchar(8) DEFAULT NULL COMMENT ' 年度月份缩写 (e.g., 2023-Jan)',
`date_key` int DEFAULT NULL COMMENT ' 日期键 (YYYYMMDD)',
PRIMARY KEY (`date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
创建日期维度表存储过程:
CREATE PROCEDURE `fill_dim_date`(IN start_date DATE, IN end_date DATE)
begin
DECLARE current_date1 DATE;
DECLARE day_name_zh VARCHAR(6);
DECLARE month_abbreviation_zh VARCHAR(3);
DECLARE quarter_name_zh VARCHAR(6);
SET current_date1 = start_date;
WHILE current_date1 <= end_date DO
-- 计算中文星期几
CASE DAYOFWEEK(current_date1)
WHEN 1 THEN SET day_name_zh = '星期日';
WHEN 2 THEN SET day_name_zh = '星期一';
WHEN 3 THEN SET day_name_zh = '星期二';
WHEN 4 THEN SET day_name_zh = '星期三';
WHEN 5 THEN SET day_name_zh = '星期四';
WHEN 6 THEN SET day_name_zh = '星期五';
WHEN 7 THEN SET day_name_zh = '星期六';
END CASE;
-- 计算中文月份缩写
CASE MONTH(current_date1)
WHEN 1 THEN SET month_abbreviation_zh = '一月';
WHEN 2 THEN SET month_abbreviation_zh = '二月';
WHEN 3 THEN SET month_abbreviation_zh = '三月';
WHEN 4 THEN SET month_abbreviation_zh = '四月';
WHEN 5 THEN SET month_abbreviation_zh = '五月';
WHEN 6 THEN SET month_abbreviation_zh = '六月';
WHEN 7 THEN SET month_abbreviation_zh = '七月';
WHEN 8 THEN SET month_abbreviation_zh = '八月';
WHEN 9 THEN SET month_abbreviation_zh = '九月';
WHEN 10 THEN SET month_abbreviation_zh = '十月';
WHEN 11 THEN SET month_abbreviation_zh = '十一月';
WHEN 12 THEN SET month_abbreviation_zh = '十二月';
END CASE;
-- 计算中文季度名称
CASE QUARTER(current_date1)
WHEN 1 THEN SET quarter_name_zh = '第一季度';
WHEN 2 THEN SET quarter_name_zh = '第二季度';
WHEN 3 THEN SET quarter_name_zh = '第三季度';
WHEN 4 THEN SET quarter_name_zh = '第四季度';
END CASE;
-- 插入日期数据
INSERT INTO dim_date (
`date`,
`date_short`,
`date_medium`,
`date_long`,
`date_full`,
`day_in_year`,
`day_in_month`,
`day_name`,
`day_abbreviation`,
`day_abbreviation_zh`,
`week_in_year`,
`week_in_month`,
`month_number`,
`month_abbreviation`,
`month_abbreviation_zh`,
`year2`,
`year4`,
`quarter_name`,
`quarter_name_zh`,
`quarter_number`,
`is_first_day_in_week`,
`is_last_day_in_week`,
`is_first_day_in_month`,
`is_last_day_in_month`,
`year_quarter`,
`year_month_number`,
`year_month_abbreviation`,
`date_key`
) VALUES (
current_date1,
DATE_FORMAT(current_date1, '%y/%m/%d'), -- 短日期格式
DATE_FORMAT(current_date1, '%b %d, %Y'), -- 中日期格式
DATE_FORMAT(current_date1, '%M %d, %Y'), -- 长日期格式
DATE_FORMAT(current_date1, '%W, %M %d, %Y'), -- 完整日期格式
DAYOFYEAR(current_date1), -- 一年中的第几天
DAY(current_date1), -- 一月中的第几天
DAYNAME(current_date1), -- 完整星期几名称
LEFT(DAYNAME(current_date1), 3), -- 星期几缩写
day_name_zh, -- 中文星期几缩写
WEEKOFYEAR(current_date1), -- 一年中的第几周
WEEK(current_date1, 5) - WEEK(DATE_SUB(current_date1, INTERVAL DAYOFMONTH(current_date1) - 1 DAY), 5) + 1, -- 一月中的第几周
MONTH(current_date1), -- 月份编号
DATE_FORMAT(current_date1, '%b'), -- 月份缩写
month_abbreviation_zh, -- 中文月份缩写
DATE_FORMAT(current_date1, '%y'), -- 2位年份
DATE_FORMAT(current_date1, '%Y'), -- 4位年份
CONCAT('Q', QUARTER(current_date1)), -- 季度名称
quarter_name_zh, -- 中文季度名称
QUARTER(current_date1), -- 季度编号
IF(DAYOFWEEK(current_date1) = 1, 1, 0), -- 是否为一周的第一天
IF(DAYOFWEEK(current_date1) = 7, 1, 0), -- 是否为一周的最后一天
IF(DAY(current_date1) = 1, 1, 0), -- 是否为一个月的第一天
IF(LAST_DAY(current_date1) = current_date1, 1, 0), -- 是否为一个月的最后一天
CONCAT(YEAR(current_date1), '-Q', QUARTER(current_date1)), -- 年度季度
DATE_FORMAT(current_date1, '%Y-%m'), -- 年度月份编号
DATE_FORMAT(current_date1, '%Y-%b'), -- 年度月份缩写
DATE_FORMAT(current_date1, '%Y%m%d') -- 日期键
);
-- 将日期加1天
SET current_date1 = DATE_ADD(current_date1, INTERVAL 1 DAY);
END WHILE;
END
执行
call fill_dim_date('2024-01-01','2024-09-15')
技术点
设置全局变量 default_week_format
你可以通过设置 MySQL 的全局或会话变量 default_week_format 来更改默认的周计算方式,使得周一为一周的第一天。
SET @@global.default_week_format = 1; -- 设置全局默认周格式,周一为一周的第一天
SET @@session.default_week_format = 1; -- 设置当前会话的默认周格式
此变量值 1 表示周一为一周的第一天。如果你需要在整个 MySQL 会话中使用周一作为一周的第一天,可以在会话开始时设置。