时间维度表的制作
1 需求背景
在大数据分析模块中,我们需要从不同的维度分析主题表,包括常用的公用维度:时间维,地区维度,教育信息维…以及各种各样的业务维度:员工维度,部门维度…,业务维度就是我们从哪些角度去分析业务过程,本文就是做一张常用时间维度表。
时间维表由于是可预见的,因此可以一次性导入未来几十年的,当然对于一些节假日的设置可能只能获取未来一年的,因此可以每年全量更新一次。
2 维表设计
给出时间维度表的建表语句
CREATE DATABASE dim_db DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; drop table dim_db.dim_date; create table if not exists dim_db.dim_date ( udate varchar(20) comment '日期', uyear varchar(20) comment '年', uquarter varchar(20) comment '季度', useason varchar(20) comment '季节', umonth varchar(20) comment '月', uday varchar(20) comment '日', uweek varchar(20) comment '第几周', uweekday varchar(20) comment '周几:1-周一、2-周二、3-周三、4-周四、5-周五、6-周六、7-周日', is_workday varchar(20) comment '是否是工作日:1,0', udatetype varchar(20) comment '节假日类型:工作日,法定上班[还班],周末,节假日', updatedate varchar(20) comment '数据更新日期' );
这里额外解释三个字段
uquarter: 季度,按照阳历的日期分的,[1,2,3]第一季度,[4,5,6]为第二季度,[7,8,9]为第三季度,[10,11,12]为第四季度。
useason:季节,季节的划分有三种方式,本采用的是节气划分法。
-
天文划分法,以春分、夏至、秋分、冬至为四季的开始;
-
气象划分法,以3月至5月为春季,6月至8月为夏季,9月至11月为秋季,12月至2月为冬季;
-
节气划分法,以立春、立夏、立秋、立冬为四季之始。
udatetype:法定上班指的是因为放假调休周末也要上班的日期,节假日会直接显示日期名称,实现的逻辑大家可以自行更改。
3 实现方式
3.1 安装库
本文实现的方式是基于python的chinese_calendar库和pymysql库将数据导入到mysql,接着生成csv文件导入导hive数据库里面。
- MySQL:5.6.36 本地部署
- chinese_calendar:1.8.0 这是一个基于阿里云开发的中国日历库,每年会更新
- pymysql:1.0.2 连接mysql用的
- python版本:3.7
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple chinesecalendar
pip install pymysql
3.2 实现代码
import chinese_calendar import pymysql.cursors import datetime import pytz def main(): # (1)设置生成表中数据的开始和截至日期 start_date = datetime.date(2010, 1, 1) end_date = datetime.date(2023, 12, 31) # (2)获取该时间段内所有的日期 dates = chinese_calendar.get_dates(start_date, end_date) # (3)遍历日期,构造sql字符串 strsql = '''INSERT INTO `dim_date`(`udate`,`uyear`,`uquarter`,`useason`,`umonth`,`uday`,`uweek`,`uweekday`,`is_workday`,`udateType`,`updatedate`)VALUES''' is_first_line = True # (4)设置生成节气的起始时间和截至日期 # 因为需要 立春,立夏,立秋,立冬四个字段的名称,所以 [数据项的开始日期和截至日期区间] 应在 [节气的起始时间和截至日期的区间]内 solar_term_start_date = datetime.date(2009, 11, 7) solar_term_end_date = datetime.date(2030, 12, 31) season_start_date_list = get_season_start_date_list(solar_term_start_date, solar_term_end_date) # get_current_season_index index = get_current_season_index(season_start_date_list, start_date) # (5)遍历日期集合构造sql for date in dates: # [1]udate: 日期 udate = date.__str__() # [2]uyear: 年份 uyear = str(date.year) # [3]umonth: 月份 umonth = str(date.month) # [4]uquarter: 季度 uquarter = get_quarter(date.month) # [5]useason: 季节 useason = '' if season_start_date_list[index][0] <= date < season_start_date_list[index + 1][0]: useason = season_start_date_list[index][1] elif date >= season_start_date_list[index + 1][0]: index += 1 useason = season_start_date_list[index][1] # [6]uday: 日 uday = str(date.day) # [7]uweek: 第几周 # 构造一个指定日期时间,时区[必选]的datetime 对象 timezone = pytz.timezone('Asia/Shanghai') dt = datetime.datetime(date.year, date.month, date.day, tzinfo=timezone) uweek = str(int(dt.strftime("%U")) + 1) # [7]uweekday: 周几 uweekday = str(date.isoweekday()) # is_holiday, holidays = chinese_calendar.get_holiday_detail(date) is_workday = '1' if chinese_calendar.is_workday(date) else '0' # [9]udatetype: 日期类型 udatetype = '' if is_workday == '1': if date.isoweekday() in [6, 7]: # udatetype = '法定上班' is_holiday, holidays = chinese_calendar.get_holiday_detail(date) udatetype = '法定上班-' + get_chinese_name(holidays) else: udatetype = '工作日' else: is_holiday, holidays = chinese_calendar.get_holiday_detail(date) if holidays is None: udatetype = '周末' else: udatetype = get_chinese_name(str(holidays)) # [10]updatedate: 更新时间,默认是当天 updatedate = datetime.date.today().__str__() # updatedate = datetime.date(2023, 5, 12).__str__() 手动指定更新日期 # 判断是否首行 if is_first_line: is_first_line = False else: strsql += ',' # 构建单行数据库文本记录 linerecord = '(\'' + udate + '\',\'' \ + uyear + '\',\'' \ + uquarter + '\',\'' \ + useason + '\',\'' \ + umonth + '\',\'' \ + uday + '\',\'' \ + uweek + '\',\'' \ + uweekday + '\',\'' \ + is_workday + '\',\'' \ + udatetype + '\',\'' \ + updatedate + '\')' print(linerecord) # 连接sql strsql += linerecord strsql += ';' # (4)将生成的数据插入到数据库 # 连接配置信息 config = { 'host': '127.0.0.1', 'port': 3306, 'user': 'root', 'password': '你的数据库密码', 'db': 'dim_dib', 'charset': 'utf8', 'cursorclass': pymysql.cursors.DictCursor, } # 创建连接 connection = pymysql.connect(**config) # 使用cursor创建游标对象 cursor = connection.cursor() # 执行sql语句 cursor.execute(strsql) connection.commit() # 关闭连接 cursor.close() connection.close() def get_quarter(month): ''' 获取月份对应的季度 :param month: 月份 :return: 季度 ''' if month in [1, 2, 3]: return '1' elif month in [4, 5, 6]: return '2' elif month in [7, 8, 9]: return '3' elif month in [10, 11, 12]: return '4' else: return None def get_chinese_name(english_name): ''' 将英文节日名称映射成中文名称 :param english_name: str :return: str ''' if english_name == "New Year's Day": return "元旦" elif english_name == "Spring Festival": return "春节" elif english_name == "Tomb-sweeping Day": return "清明" elif english_name == "Dragon Boat Festival": return "端午" elif english_name == "Labour Day": return "劳动节" elif english_name == "National Day": return "国庆节" elif english_name == "Mid-autumn Festival": return "中秋" else: return "无效节日" def get_season_start_date_list(start_date, end_date): ''' 返回[每个季节开始的日期和名称]的集合 目前可求的范围是:[1900, 2100] :param start_date: 起始时间 :param end_date: 结束时间 :return: list,元素内容:(date,'春季'),或者(date,'夏季'),(date,'秋季'),(date,'冬季') ''' solar_terms = chinese_calendar.get_solar_terms(start_date, end_date) date_season_list = [] for term in solar_terms: term_name = term[1] udate = term[0] if term_name == '立春': date_season_list.append((udate, '春季')) elif term_name == '立夏': date_season_list.append((udate, '夏季')) elif term_name == '立秋': date_season_list.append((udate, '秋季')) elif term_name == '立冬': date_season_list.append((udate, '冬季')) return date_season_list def get_current_season_index(season_start_date_list, start_date): ''' 获取起始时间对应季节的起始时间 :param season_start_date_list: 每个季节起始时间的日期集合以及相应的季节名称 :param start_date: 起始时间 :return: 起始时间对应季节的起始时间 | 集合的下标 ''' for index in range(0,12000): if start_date >= season_start_date_list[index][0]: return index if __name__ == '__main__': main()
3.3 生成数据和更新
使用程序的时候只需要设置程序最开始的start_date和end_date,更新数据同理,不过后续更新数据的时候应该选择更高版本的chinese_calendar库。
4 生成数据预览
这里贴出来了2010年一整年的数据,datagrip导出来的,已经核对过数据是没有问题的,大家可以在http://www.gov.cn/zwgk/2009-12/08/content_1482691.htm国务院办公厅发布的节假日安排核对假日信息,手机日历上的节假日信息个别有偏差。
udate uyear uquarter useason umonth uday uweek uweekday is_workday udatetype updatedate 2010-01-01 2010 1 冬季 1 1 1 5 0 元旦 2023-05-12 2010-01-02 2010 1 冬季 1 2 1 6 0 元旦 2023-05-12 2010-01-03 2010 1 冬季 1 3 2 7 0 元旦 2023-05-12 2010-01-04 2010 1 冬季 1 4 2 1 1 工作日 2023-05-12 2010-01-05 2010 1 冬季 1 5 2 2 1 工作日 2023-05-12 2010-01-06 2010 1 冬季 1 6 2 3 1 工作日 2023-05-12 2010-01-07 2010 1 冬季 1 7 2 4 1 工作日 2023-05-12 2010-01-08 2010 1 冬季 1 8 2 5 1 工作日 2023-05-12 2010-01-09 2010 1 冬季 1 9 2 6 0 周末 2023-05-12 2010-01-10 2010 1 冬季 1 10 3 7 0 周末 2023-05-12 2010-01-11 2010 1 冬季 1 11 3 1 1 工作日 2023-05-12 2010-01-12 2010 1 冬季 1 12 3 2 1 工作日 2023-05-12 2010-01-13 2010 1 冬季 1 13 3 3 1 工作日 2023-05-12 2010-01-14 2010 1 冬季 1 14 3 4 1 工作日 2023-05-12 2010-01-15 2010 1 冬季 1 15 3 5 1 工作日 2023-05-12 2010-01-16 2010 1 冬季 1 16 3 6 0 周末 2023-05-12 2010-01-17 2010 1 冬季 1 17 4 7 0 周末 2023-05-12 2010-01-18 2010 1 冬季 1 18 4 1 1 工作日 2023-05-12 2010-01-19 2010 1 冬季 1 19 4 2 1 工作日 2023-05-12 2010-01-20 2010 1 冬季 1 20 4 3 1 工作日 2023-05-12 2010-01-21 2010 1 冬季 1 21 4 4 1 工作日 2023-05-12 2010-01-22 2010 1 冬季 1 22 4 5 1 工作日 2023-05-12 2010-01-23 2010 1 冬季 1 23 4 6 0 周末 2023-05-12 2010-01-24 2010 1 冬季 1 24 5 7 0 周末 2023-05-12 2010-01-25 2010 1 冬季 1 25 5 1 1 工作日 2023-05-12 2010-01-26 2010 1 冬季 1 26 5 2 1 工作日 2023-05-12 2010-01-27 2010 1 冬季 1 27 5 3 1 工作日 2023-05-12 2010-01-28 2010 1 冬季 1 28 5 4 1 工作日 2023-05-12 2010-01-29 2010 1 冬季 1 29 5 5 1 工作日 2023-05-12 2010-01-30 2010 1 冬季 1 30 5 6 0 周末 2023-05-12 2010-01-31 2010 1 冬季 1 31 6 7 0 周末 2023-05-12 2010-02-01 2010 1 冬季 2 1 6 1 1 工作日 2023-05-12 2010-02-02 2010 1 冬季 2 2 6 2 1 工作日 2023-05-12 2010-02-03 2010 1 冬季 2 3 6 3 1 工作日 2023-05-12 2010-02-04 2010 1 春季 2 4 6 4 1 工作日 2023-05-12 2010-02-05 2010 1 春季 2 5 6 5 1 工作日 2023-05-12 2010-02-06 2010 1 春季 2 6 6 6 0 周末 2023-05-12 2010-02-07 2010 1 春季 2 7 7 7 0 周末 2023-05-12 2010-02-08 2010 1 春季 2 8 7 1 1 工作日 2023-05-12 2010-02-09 2010 1 春季 2 9 7 2 1 工作日 2023-05-12 2010-02-10 2010 1 春季 2 10 7 3 1 工作日 2023-05-12 2010-02-11 2010 1 春季 2 11 7 4 1 工作日 2023-05-12 2010-02-12 2010 1 春季 2 12 7 5 1 工作日 2023-05-12 2010-02-13 2010 1 春季 2 13 7 6 0 春节 2023-05-12 2010-02-14 2010 1 春季 2 14 8 7 0 春节 2023-05-12 2010-02-15 2010 1 春季 2 15 8 1 0 春节 2023-05-12 2010-02-16 2010 1 春季 2 16 8 2 0 春节 2023-05-12 2010-02-17 2010 1 春季 2 17 8 3 0 春节 2023-05-12 2010-02-18 2010 1 春季 2 18 8 4 0 春节 2023-05-12 2010-02-19 2010 1 春季 2 19 8 5 0 春节 2023-05-12 2010-02-20 2010 1 春季 2 20 8 6 1 法定上班 2023-05-12 2010-02-21 2010 1 春季 2 21 9 7 1 法定上班 2023-05-12 2010-02-22 2010 1 春季 2 22 9 1 1 工作日 2023-05-12 2010-02-23 2010 1 春季 2 23 9 2 1 工作日 2023-05-12 2010-02-24 2010 1 春季 2 24 9 3 1 工作日 2023-05-12 2010-02-25 2010 1 春季 2 25 9 4 1 工作日 2023-05-12 2010-02-26 2010 1 春季 2 26 9 5 1 工作日 2023-05-12 2010-02-27 2010 1 春季 2 27 9 6 0 周末 2023-05-12 2010-02-28 2010 1 春季 2 28 10 7 0 周末 2023-05-12 2010-03-01 2010 1 春季 3 1 10 1 1 工作日 2023-05-12 2010-03-02 2010 1 春季 3 2 10 2 1 工作日 2023-05-12 2010-03-03 2010 1 春季 3 3 10 3 1 工作日 2023-05-12 2010-03-04 2010 1 春季 3 4 10 4 1 工作日 2023-05-12 2010-03-05 2010 1 春季 3 5 10 5 1 工作日 2023-05-12 2010-03-06 2010 1 春季 3 6 10 6 0 周末 2023-05-12 2010-03-07 2010 1 春季 3 7 11 7 0 周末 2023-05-12 2010-03-08 2010 1 春季 3 8 11 1 1 工作日 2023-05-12 2010-03-09 2010 1 春季 3 9 11 2 1 工作日 2023-05-12 2010-03-10 2010 1 春季 3 10 11 3 1 工作日 2023-05-12 2010-03-11 2010 1 春季 3 11 11 4 1 工作日 2023-05-12 2010-03-12 2010 1 春季 3 12 11 5 1 工作日 2023-05-12 2010-03-13 2010 1 春季 3 13 11 6 0 周末 2023-05-12 2010-03-14 2010 1 春季 3 14 12 7 0 周末 2023-05-12 2010-03-15 2010 1 春季 3 15 12 1 1 工作日 2023-05-12 2010-03-16 2010 1 春季 3 16 12 2 1 工作日 2023-05-12 2010-03-17 2010 1 春季 3 17 12 3 1 工作日 2023-05-12 2010-03-18 2010 1 春季 3 18 12 4 1 工作日 2023-05-12 2010-03-19 2010 1 春季 3 19 12 5 1 工作日 2023-05-12 2010-03-20 2010 1 春季 3 20 12 6 0 周末 2023-05-12 2010-03-21 2010 1 春季 3 21 13 7 0 周末 2023-05-12 2010-03-22 2010 1 春季 3 22 13 1 1 工作日 2023-05-12 2010-03-23 2010 1 春季 3 23 13 2 1 工作日 2023-05-12 2010-03-24 2010 1 春季 3 24 13 3 1 工作日 2023-05-12 2010-03-25 2010 1 春季 3 25 13 4 1 工作日 2023-05-12 2010-03-26 2010 1 春季 3 26 13 5 1 工作日 2023-05-12 2010-03-27 2010 1 春季 3 27 13 6 0 周末 2023-05-12 2010-03-28 2010 1 春季 3 28 14 7 0 周末 2023-05-12 2010-03-29 2010 1 春季 3 29 14 1 1 工作日 2023-05-12 2010-03-30 2010 1 春季 3 30 14 2 1 工作日 2023-05-12 2010-03-31 2010 1 春季 3 31 14 3 1 工作日 2023-05-12 2010-04-01 2010 2 春季 4 1 14 4 1 工作日 2023-05-12 2010-04-02 2010 2 春季 4 2 14 5 1 工作日 2023-05-12 2010-04-03 2010 2 春季 4 3 14 6 0 清明 2023-05-12 2010-04-04 2010 2 春季 4 4 15 7 0 清明 2023-05-12 2010-04-05 2010 2 春季 4 5 15 1 0 清明 2023-05-12 2010-04-06 2010 2 春季 4 6 15 2 1 工作日 2023-05-12 2010-04-07 2010 2 春季 4 7 15 3 1 工作日 2023-05-12 2010-04-08 2010 2 春季 4 8 15 4 1 工作日 2023-05-12 2010-04-09 2010 2 春季 4 9 15 5 1 工作日 2023-05-12 2010-04-10 2010 2 春季 4 10 15 6 0 周末 2023-05-12 2010-04-11 2010 2 春季 4 11 16 7 0 周末 2023-05-12 2010-04-12 2010 2 春季 4 12 16 1 1 工作日 2023-05-12 2010-04-13 2010 2 春季 4 13 16 2 1 工作日 2023-05-12 2010-04-14 2010 2 春季 4 14 16 3 1 工作日 2023-05-12 2010-04-15 2010 2 春季 4 15 16 4 1 工作日 2023-05-12 2010-04-16 2010 2 春季 4 16 16 5 1 工作日 2023-05-12 2010-04-17 2010 2 春季 4 17 16 6 0 周末 2023-05-12 2010-04-18 2010 2 春季 4 18 17 7 0 周末 2023-05-12 2010-04-19 2010 2 春季 4 19 17 1 1 工作日 2023-05-12 2010-04-20 2010 2 春季 4 20 17 2 1 工作日 2023-05-12 2010-04-21 2010 2 春季 4 21 17 3 1 工作日 2023-05-12 2010-04-22 2010 2 春季 4 22 17 4 1 工作日 2023-05-12 2010-04-23 2010 2 春季 4 23 17 5 1 工作日 2023-05-12 2010-04-24 2010 2 春季 4 24 17 6 0 周末 2023-05-12 2010-04-25 2010 2 春季 4 25 18 7 0 周末 2023-05-12 2010-04-26 2010 2 春季 4 26 18 1 1 工作日 2023-05-12 2010-04-27 2010 2 春季 4 27 18 2 1 工作日 2023-05-12 2010-04-28 2010 2 春季 4 28 18 3 1 工作日 2023-05-12 2010-04-29 2010 2 春季 4 29 18 4 1 工作日 2023-05-12 2010-04-30 2010 2 春季 4 30 18 5 1 工作日 2023-05-12 2010-05-01 2010 2 春季 5 1 18 6 0 劳动节 2023-05-12 2010-05-02 2010 2 春季 5 2 19 7 0 劳动节 2023-05-12 2010-05-03 2010 2 春季 5 3 19 1 0 劳动节 2023-05-12 2010-05-04 2010 2 春季 5 4 19 2 1 工作日 2023-05-12 2010-05-05 2010 2 夏季 5 5 19 3 1 工作日 2023-05-12 2010-05-06 2010 2 夏季 5 6 19 4 1 工作日 2023-05-12 2010-05-07 2010 2 夏季 5 7 19 5 1 工作日 2023-05-12 2010-05-08 2010 2 夏季 5 8 19 6 0 周末 2023-05-12 2010-05-09 2010 2 夏季 5 9 20 7 0 周末 2023-05-12 2010-05-10 2010 2 夏季 5 10 20 1 1 工作日 2023-05-12 2010-05-11 2010 2 夏季 5 11 20 2 1 工作日 2023-05-12 2010-05-12 2010 2 夏季 5 12 20 3 1 工作日 2023-05-12 2010-05-13 2010 2 夏季 5 13 20 4 1 工作日 2023-05-12 2010-05-14 2010 2 夏季 5 14 20 5 1 工作日 2023-05-12 2010-05-15 2010 2 夏季 5 15 20 6 0 周末 2023-05-12 2010-05-16 2010 2 夏季 5 16 21 7 0 周末 2023-05-12 2010-05-17 2010 2 夏季 5 17 21 1 1 工作日 2023-05-12 2010-05-18 2010 2 夏季 5 18 21 2 1 工作日 2023-05-12 2010-05-19 2010 2 夏季 5 19 21 3 1 工作日 2023-05-12 2010-05-20 2010 2 夏季 5 20 21 4 1 工作日 2023-05-12 2010-05-21 2010 2 夏季 5 21 21 5 1 工作日 2023-05-12 2010-05-22 2010 2 夏季 5 22 21 6 0 周末 2023-05-12 2010-05-23 2010 2 夏季 5 23 22 7 0 周末 2023-05-12 2010-05-24 2010 2 夏季 5 24 22 1 1 工作日 2023-05-12 2010-05-25 2010 2 夏季 5 25 22 2 1 工作日 2023-05-12 2010-05-26 2010 2 夏季 5 26 22 3 1 工作日 2023-05-12 2010-05-27 2010 2 夏季 5 27 22 4 1 工作日 2023-05-12 2010-05-28 2010 2 夏季 5 28 22 5 1 工作日 2023-05-12 2010-05-29 2010 2 夏季 5 29 22 6 0 周末 2023-05-12 2010-05-30 2010 2 夏季 5 30 23 7 0 周末 2023-05-12 2010-05-31 2010 2 夏季 5 31 23 1 1 工作日 2023-05-12 2010-06-01 2010 2 夏季 6 1 23 2 1 工作日 2023-05-12 2010-06-02 2010 2 夏季 6 2 23 3 1 工作日 2023-05-12 2010-06-03 2010 2 夏季 6 3 23 4 1 工作日 2023-05-12 2010-06-04 2010 2 夏季 6 4 23 5 1 工作日 2023-05-12 2010-06-05 2010 2 夏季 6 5 23 6 0 周末 2023-05-12 2010-06-06 2010 2 夏季 6 6 24 7 0 周末 2023-05-12 2010-06-07 2010 2 夏季 6 7 24 1 1 工作日 2023-05-12 2010-06-08 2010 2 夏季 6 8 24 2 1 工作日 2023-05-12 2010-06-09 2010 2 夏季 6 9 24 3 1 工作日 2023-05-12 2010-06-10 2010 2 夏季 6 10 24 4 1 工作日 2023-05-12 2010-06-11 2010 2 夏季 6 11 24 5 1 工作日 2023-05-12 2010-06-12 2010 2 夏季 6 12 24 6 1 法定上班 2023-05-12 2010-06-13 2010 2 夏季 6 13 25 7 1 法定上班 2023-05-12 2010-06-14 2010 2 夏季 6 14 25 1 0 端午 2023-05-12 2010-06-15 2010 2 夏季 6 15 25 2 0 端午 2023-05-12 2010-06-16 2010 2 夏季 6 16 25 3 0 端午 2023-05-12 2010-06-17 2010 2 夏季 6 17 25 4 1 工作日 2023-05-12 2010-06-18 2010 2 夏季 6 18 25 5 1 工作日 2023-05-12 2010-06-19 2010 2 夏季 6 19 25 6 0 周末 2023-05-12 2010-06-20 2010 2 夏季 6 20 26 7 0 周末 2023-05-12 2010-06-21 2010 2 夏季 6 21 26 1 1 工作日 2023-05-12 2010-06-22 2010 2 夏季 6 22 26 2 1 工作日 2023-05-12 2010-06-23 2010 2 夏季 6 23 26 3 1 工作日 2023-05-12 2010-06-24 2010 2 夏季 6 24 26 4 1 工作日 2023-05-12 2010-06-25 2010 2 夏季 6 25 26 5 1 工作日 2023-05-12 2010-06-26 2010 2 夏季 6 26 26 6 0 周末 2023-05-12 2010-06-27 2010 2 夏季 6 27 27 7 0 周末 2023-05-12 2010-06-28 2010 2 夏季 6 28 27 1 1 工作日 2023-05-12 2010-06-29 2010 2 夏季 6 29 27 2 1 工作日 2023-05-12 2010-06-30 2010 2 夏季 6 30 27 3 1 工作日 2023-05-12
猜你喜欢
网友评论
- 搜索
- 最新文章
- 热门文章