数据分析SQL日期维度表生成(含节假日)
文章目录
- 概述
- Python生成日期维度表
- HIVE日期维度表
- HIVE近30天日期序列
- HIVE近48小时序列
概述
- 在商业数据分析中,需要用到日期维度
例如:绘制连续日期的销量曲线;按周、月、季聚合求和… - 按周、月、季聚合的格式:
周:2022年第01周
、2022w51
、202251
…
月:2022年01月
、2022-01
…
季:2022年第1季
、2022q1
、2022Q1
… - 在某些零售行业中,线下零售假日销量高于工作日
因此,在按周汇总时,希望以星期一作为周的起点
对于跨年,以 年内第1个星期一 作为 年的第一周,此前归入上1年最后1周,例如下面
例如,
2023-01-01
归属到2022w52
那周
Python生成日期维度表
from datetime import datetime, timedelta
from math import ceilSTART = '2022-01-01'
END = '2022-12-31'
HOLIDAY = {'2022-01-01': ('元旦', False), '2022-01-02': ('元旦', False),'2022-01-03': ('元旦', False), '2022-01-29': ('补班', True),'2022-01-30': ('补班', True), '2022-01-31': ('春节', False),'2022-02-01': ('春节', False), '2022-02-02': ('春节', False),'2022-02-03': ('春节', False), '2022-02-04': ('春节', False),'2022-02-05': ('春节', False), '2022-02-06': ('春节', False),'2022-04-02': ('补班', True), '2022-04-03': ('清明节', False),'2022-04-04': ('清明节', False), '2022-04-05': ('清明节', False),'2022-04-24': ('补班', True), '2022-04-30': ('劳动节', False),'2022-05-01': ('劳动节', False), '2022-05-02': ('劳动节', False),'2022-05-03': ('劳动节', False), '2022-05-04': ('劳动节', False),'2022-05-07': ('补班', True), '2022-06-03': ('端午节', False),'2022-06-04': ('端午节', False), '2022-06-05': ('端午节', False),'2022-09-11': ('中秋节', False), '2022-09-12': ('中秋节', False),'2022-09-10': ('中秋节', False), '2022-10-01': ('国庆节', False),'2022-10-02': ('国庆节', False), '2022-10-03': ('国庆节', False),'2022-10-04': ('国庆节', False), '2022-10-05': ('国庆节', False),'2022-10-06': ('国庆节', False), '2022-10-07': ('国庆节', False),'2022-10-08': ('补班', True), '2022-10-09': ('补班', True),
}def get_day_of_year(d: datetime) -> int:return (d - datetime(year=d.year, month=1, day=1)).days + 1def get_week_of_year(d: datetime) -> int:day_of_year = get_day_of_year(d)return ceil((day_of_year - d.weekday()) / 7)def get_weekday_cn(d: datetime) -> str:return ['周一', '周二', '周三', '周四', '周五', '周六', '周日'][d.weekday()]def get_year_week(d: datetime) -> (int, int, str):day_of_year = get_day_of_year(d)week_of_year = get_week_of_year(d)if week_of_year == 0:y = d.year - 1yw = '%04dw%02d' % (y, get_week_of_year(datetime(year=y, month=12, day=31)))else:y = d.yearyw = '%04dw%02d' % (y, week_of_year)return day_of_year, week_of_year, ywdef generate_date():start = datetime.strptime(START, '%Y-%m-%d')end = datetime.strptime(END, '%Y-%m-%d')for i in range((end - start).days + 1):d = start + timedelta(i)ymd = d.strftime('%Y-%m-%d')ym = d.strftime('%Y-%m')yq = '%d%s%d' % (d.year, 'q', ceil(d.month / 3))day_of_year, week_of_year, yw = get_year_week(d)weekday_cn = get_weekday_cn(d)holiday, is_workday = HOLIDAY.get(ymd, ('休息日' if d.weekday() > 4 else '工作日',d.weekday() < 5))print(ymd, ym, yq, yw, weekday_cn, day_of_year, week_of_year, holiday, is_workday, sep='\t')if __name__ == '__main__':generate_date()
HIVE日期维度表
datediff
SELECT datediff('2022-01-04','2022-01-01');
输出:3
repeat
SELECT repeat('a',3);
输出:aaa
split
SELECT split('aaa','a');
输出:
["","","",""]
posexplode
SELECT posexplode(split('aaa','a'));
输出:
date_add
SELECT date_add('2022-01-01',1)
输出:
2022-01-02
生成日期序列
WITH t AS (SELECT posexplode(split(repeat('a',3),'a')))
SELECT date_add('2022-01-01',pos) AS ymd FROM t;
输出:
2022-01-01
2022-01-02
2022-01-03
2022-01-04
创建节日临时表(以2022为例,缺双十一、七夕……)
CREATE TABLE temp_holiday2022 AS
SELECT '2022-01-01','元旦',false UNION ALL
SELECT '2022-01-02','元旦',false UNION ALL
SELECT '2022-01-03','元旦',false UNION ALL
SELECT '2022-01-29','补班',true UNION ALL
SELECT '2022-01-30','补班',true UNION ALL
SELECT '2022-01-31','春节',false UNION ALL
SELECT '2022-02-01','春节',false UNION ALL
SELECT '2022-02-02','春节',false UNION ALL
SELECT '2022-02-03','春节',false UNION ALL
SELECT '2022-02-04','春节',false UNION ALL
SELECT '2022-02-05','春节',false UNION ALL
SELECT '2022-02-06','春节',false UNION ALL
SELECT '2022-04-02','补班',true UNION ALL
SELECT '2022-04-03','清明节',false UNION ALL
SELECT '2022-04-04','清明节',false UNION ALL
SELECT '2022-04-05','清明节',false UNION ALL
SELECT '2022-04-24','补班',true UNION ALL
SELECT '2022-04-30','劳动节',false UNION ALL
SELECT '2022-05-01','劳动节',false UNION ALL
SELECT '2022-05-02','劳动节',false UNION ALL
SELECT '2022-05-03','劳动节',false UNION ALL
SELECT '2022-05-04','劳动节',false UNION ALL
SELECT '2022-05-07','补班',true UNION ALL
SELECT '2022-06-03','端午节',false UNION ALL
SELECT '2022-06-04','端午节',false UNION ALL
SELECT '2022-06-05','端午节',false UNION ALL
SELECT '2022-09-11','中秋节',false UNION ALL
SELECT '2022-09-12','中秋节',false UNION ALL
SELECT '2022-09-10','中秋节',false UNION ALL
SELECT '2022-10-01','国庆节',false UNION ALL
SELECT '2022-10-02','国庆节',false UNION ALL
SELECT '2022-10-03','国庆节',false UNION ALL
SELECT '2022-10-04','国庆节',false UNION ALL
SELECT '2022-10-05','国庆节',false UNION ALL
SELECT '2022-10-06','国庆节',false UNION ALL
SELECT '2022-10-07','国庆节',false UNION ALL
SELECT '2022-10-08','补班',true UNION ALL
SELECT '2022-10-09','补班',true;SELECT `_c0`,`_c1`,`_c2` FROM temp_holiday2022 ORDER BY `_c0`;
生成日期维度
WITH
t0 AS (SELECT posexplode(split(repeat('a',datediff('2022-12-31','2022-01-01')),'a'))),
t1 AS (SELECT date_add('2022-01-01',pos) AS d FROM t0),
t2 AS (SELECT date_format(d,'yyyy-MM-dd') AS ymd,year(d) AS y,date_format(d,'yyyy-MM') AS ym,concat(year(d),'q',quarter(d)) AS yq,CAST(date_format(d,'D') AS SMALLINT) AS day_of_year,CAST(date_format(d,'w') AS SMALLINT) AS week_of_year,CAST(date_format(d,'u') AS TINYINT) AS day_of_week,date_format(d,'EEEE') AS day_of_week_enFROM t1
)
SELECT t2.*,NVL(`_c1`,IF(day_of_week>5,'休息日','工作日')) AS holiday,NVL(`_c2`,day_of_week<6) AS is_workday
FROM t2
LEFT JOIN temp_holiday2022 ON ymd=`_c0`;
日期维度表
CREATE TABLE dim_date (ymd STRING COMMENT '日期',y INT COMMENT '年',ym STRING COMMENT '年月',yq STRING COMMENT '季度',day_of_year SMALLINT COMMENT '一年中的第几天',week_of_year TINYINT COMMENT '一年中的第几周,以周日为起点',day_of_week TINYINT COMMENT '星期',day_of_week_en STRING COMMENT '星期',holiday STRING COMMENT '节假日',is_workday BOOLEAN COMMENT 'true=工作日、false=休息日'
) COMMENT '日期维度表';INSERT INTO TABLE dim_date
SELECT t2.*,NVL(`_c1`,IF(day_of_week>5,'休息日','工作日')) AS holiday,NVL(`_c2`,day_of_week<6) AS is_workday
FROM (SELECT date_format(d,'yyyy-MM-dd') AS ymd,year(d) AS y,date_format(d,'yyyy-MM') AS ym,concat(year(d),'q',quarter(d)) AS yq,CAST(date_format(d,'D') AS SMALLINT) AS day_of_year,CAST(date_format(d,'w') AS SMALLINT) AS week_of_year,CAST(date_format(d,'u') AS TINYINT) AS day_of_week,date_format(d,'EEEE') AS day_of_week_enFROM (SELECT date_add('2022-01-01',pos) AS d FROM (SELECT posexplode(split(repeat('a',datediff('2022-12-31','2022-01-01')),'a')))t0)t1
)t2
LEFT JOIN temp_holiday2022 ON ymd=`_c0`;
HIVE近30天日期序列
-- 近30天
WITH t AS (SELECT posexplode(split(repeat('a',29),'a')))
SELECT date_sub(current_date(),pos) AS ymd FROM t ORDER BY ymd;-- 1~31天前
WITH t AS (SELECT posexplode(split(repeat('a',29),'a')))
SELECT date_sub(current_date(),pos+1) AS ymd FROM t ORDER BY ymd;
-- 近7天
WITH t AS (SELECT posexplode(split(repeat('a',6),'a')))
SELECT date_sub(current_date(),pos) AS ymd FROM t ORDER BY ymd;-- 1~8天前
WITH t AS (SELECT posexplode(split(repeat('a',6),'a')))
SELECT date_sub(current_date(),pos+1) AS ymd FROM t ORDER BY ymd;
昨天1024:
2022-10-18
2022-10-19
2022-10-20
2022-10-21
2022-10-22
2022-10-23
2022-10-24
HIVE近48小时序列
WITH t AS (SELECT posexplode(split(repeat('a',47),'a')))
SELECT date_format(from_unixtime(unix_timestamp()-((pos+1)*3600)),'yyyy-MM-dd HH') AS h
FROM t ORDER BY h;
2022-10-25 08:42时刻的搜索结果:
2022-10-23 08
2022-10-23 09
2022-10-23 10
2022-10-23 11
2022-10-23 12
2022-10-23 13
2022-10-23 14
2022-10-23 15
2022-10-23 16
2022-10-23 17
2022-10-23 18
2022-10-23 19
2022-10-23 20
2022-10-23 21
2022-10-23 22
2022-10-23 23
2022-10-24 00
2022-10-24 01
2022-10-24 02
2022-10-24 03
2022-10-24 04
2022-10-24 05
2022-10-24 06
2022-10-24 07
2022-10-24 08
2022-10-24 09
2022-10-24 10
2022-10-24 11
2022-10-24 12
2022-10-24 13
2022-10-24 14
2022-10-24 15
2022-10-24 16
2022-10-24 17
2022-10-24 18
2022-10-24 19
2022-10-24 20
2022-10-24 21
2022-10-24 22
2022-10-24 23
2022-10-25 00
2022-10-25 01
2022-10-25 02
2022-10-25 03
2022-10-25 04
2022-10-25 05
2022-10-25 06
2022-10-25 07
数据分析SQL日期维度表生成(含节假日)相关推荐
- 教你用SQL生成一张带「农历」的日期维度表
点上方关注"SQL数据库开发", 设为"置顶或星标",第一时间送达干货 之前已经发布过使用存储过程,生存指定年份的日历表<SQL如何制作一张日历维度表&g ...
- 一个sql生成hive日期维度表
目录 1.日期维度表 2.生成语句 3.用例 在进行日期处理时,有时候会很麻烦,于是小编开发了一张日期维表,供大家参考. 1.日期维度表 num 字段名 字段中文名 描述 数据类型 1 date 日期 ...
- python生成日期列表_PYTHON生成日期维度表
数据仓库的定义之一是反应历史变化,数据或多或少都会包含时间特征,因此日期维度就成了数据仓库中不可或缺的维度之一,可以说在任何一个事实表中都会有一个或者多个日期维度的外键.日期维度可以尽可能多的包含日期 ...
- hive生成日期维度表Hql
hive生成日期维度表 利用现有的函数,生成维度表 表结构 日期key 具体日期 第几月份 第几季度 年份 周几 当前周的第几天 当前月的第几天 当前年的第几天 当前年的第几周 当前周的第一天 当前周 ...
- MYSQL 生成日期维度表
这里写自定义目录标题 MYSQL 生成日期维度表 1.创建建维度表 2.生成维度数据函数 MYSQL 生成日期维度表 在报表统计中经常要用到日期维度进行汇总,所以需要提前生成通用的日期维度表. 1.创 ...
- 数据仓库之日期维度表构建
导读 大家好,今日立秋,立秋是阳气渐收.阴气渐长,由阳盛逐渐转变为阴盛的转折.我们上一篇文章 数据仓库之维度表 介绍了数据仓库中维度表,本篇文章在此基础上介绍和构建维度表中的日期维度.Kimball ...
- 如何用SQL生成一张日期维度表?
点击关注公众号,SQL干货及时获取 后台回复:1024,获取海量学习资源 问题描述 输入想要生成日历的年份,通过调用存储过程,即可生成该年的全部日历. 创建表结构 我们根据常见的日历表来创建一个含有年 ...
- Kettle生成日期维度数据(数仓项目)
目录 生成日期维度数据 Hive创建日期维度表 使用Kettle构建以下组件结构图 组件配置 验证数据 报错,请看这 生成日期维度数据 经过需求分析我们发现指标统计需要的日期类型比较多如果在事实表的时 ...
- 数仓模型之维度表技术
维度表概念 维, 是人们观察数据的特定角度,是考虑问题时的一类属性,属性集合构成一个维. 维度是维度建模的基础和灵魂. 维度属性是查询约束条件.分组和报表标签生成的基本来源,是数据易用性的关键. 维度 ...
- 数据仓库建模(四):维度表的设计
数据仓库建模(四):维度表的设计 一.维度表的整体结构 1.1 维度表的结构设计 1.2 维度代理键 1.3 自然键.超久键和超自然键 1.4 下钻与上卷 1.5 维度退化 1.6 非规范化的扁平维度 ...
最新文章
- java数据库设计工具_Java课程设计---创建数据库工具类
- max7219c语言,(转)MAX7219 C语言版驱动程序
- Maven Tomcat 部署
- Lua协程Coroutine是什么
- Linux目录/bin、/sbin、/usr/bin、/usr/sbin的区别
- windows。forms.timer设置第一次不等待_适用于初学者的中线交易策略——金叉的三种设置条件...
- PyTorch实战福利从入门到精通之六——线性回归
- yum更新指定的软件
- 如何使用git把本地代码上传(更新)到github上
- linux中pak命令,Linux下Flatpak的安装与使用超详细教程
- 古今地名对照总表!(按笔划数排序,强烈推荐的资料)
- 怎样用软件测试主机电源,电脑电源功率怎么测试
- 【前端小技能】ElementUI表格双击可编辑--开箱即用
- webrtc中视频采集实现分析(一) 采集及图像处理接口封装
- ubuntu安装视频播放器
- Qt程序在arm板上运行
- 【翻译】听觉刺激增强深度睡眠,实现“熟睡自由”
- 联发科技嵌入式_【MTK联发科技工资】嵌入式软件工程师待遇-看准网
- 使用Python编写一个倒计时程序
- 眼球中心定位跟踪算法—eyelike
热门文章
- 并发队列中迭代器弱一致性原理探究
- OpenWrt路由器无线中继、桥接、信号放大、访客网络的实现方案
- 第一次学游泳技巧_第一次学游泳作文600字(5篇)
- python apkg_GitHub - TonyDongGuaPi/pc_wxapkg_decrypt_python: PC微信小程序 wxapkg 解密
- wieshark导出ftp文件_【FTP】Wireshark学习FTP流程
- python数字时钟
- 线性代数笔记2:基本子空间的正交性及性质
- Your GPU Compute Capability计算能力
- MATLAB最小矩形法边界法,最小外接矩形法.PPT
- TRAS为springcloud提供高性能的RPC能力