SQL 打印全年日历
时间:2022-07-22
本文章向大家介绍SQL 打印全年日历,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
上文我们实现了“打印一个月日历”的需求,今天在原来的基础实现一个更复杂的需求:打印一年的日历。
其实,打印一年的日历和打印一个月的实现思路很相似,本质上都是通过行转列实现,只不过年历要考虑的东西多一点。
如上图,如果我们要输出 4 x 3 版式的年历,要考虑哪些地方?
- 观察图片可知,这里的年历的月份和上文的月历不同的地方是星期天放在一周的前面,因此获取日期所在周的函数的参数要调整。
- 1月、2月、3月 在第一队,4月、5月、6月 在第二队,7月、8月、9月 在第三队,10月、11月、12月 在第四队。我们暂时把一个月的数据当成一个整体,通过公式
n = FLOOR((当前月 - 1) / 3)
计算出每个月份被放在第几队。 - 同一队里面每个月份的同一周的数据都处于同一排。每个月最多只有 5 周,我们能计算出在一个月里面每个日期分别处于哪一周。由于
WEEK
函数计算的是当前日期在一年里面处于第几周,要计算 1 月以后每个日期在它所在的月份里面属于第几周,可通过公式WEEK(当前日期)-WEEK(上个月最后一天的日期)
得到。比如WEEK('2020-01-31') = 4
,WEEK('2020-02-01') = 4
,那么 2020-02-01 这个日期在 2 月份里面就在第 0 周。
具体实现的 SQL 如下:
SET @someday := CURDATE();SELECT MAX(IF(m % 3 = 1 AND row_no = 0, m, '')) AS '月份', MAX(IF(m % 3 = 1, Sun, '')) AS '日', MAX(IF(m % 3 = 1, Mon, '')) AS '一', MAX(IF(m % 3 = 1, Tue, '')) AS '二', MAX(IF(m % 3 = 1, Wed, '')) AS '三', MAX(IF(m % 3 = 1, Thur, '')) AS '四', MAX(IF(m % 3 = 1, Fri, '')) AS '五', MAX(IF(m % 3 = 1, Sat, '')) AS '六', MAX(IF(m % 3 = 2 AND row_no = 0, m, '')) AS '月份', MAX(IF(m % 3 = 2, Sun, '')) AS '日', MAX(IF(m % 3 = 2, Mon, '')) AS '一', MAX(IF(m % 3 = 2, Tue, '')) AS '二', MAX(IF(m % 3 = 2, Wed, '')) AS '三', MAX(IF(m % 3 = 2, Thur, '')) AS '四', MAX(IF(m % 3 = 2, Fri, '')) AS '五', MAX(IF(m % 3 = 2, Sat, '')) AS '六', MAX(IF(m % 3 = 0 AND row_no = 0, m, '')) AS '月份', MAX(IF(m % 3 = 0, Sun, '')) AS '日', MAX(IF(m % 3 = 0, Mon, '')) AS '一', MAX(IF(m % 3 = 0, Tue, '')) AS '二', MAX(IF(m % 3 = 0, Wed, '')) AS '三', MAX(IF(m % 3 = 0, Thur, '')) AS '四', MAX(IF(m % 3 = 0, Fri, '')) AS '五', MAX(IF(m % 3 = 0, Sat, '')) AS '六' FROM ( /* 使用会话变量实现开窗函数的功能,计算每个日期在所在月份里面的相对周 */ SELECT flag, m, wk, Mon, Tue, Wed, Thur, Fri, Sat, Sun, @wk_month := IF(m = @month, @wk_month, wk), wk - @wk_month AS row_no, @month := m, @week := wk FROM ( /* 把月份当成一个整体,所有的月份的数据都在同一“列”*/ SELECT flag, m, wk, MAX(IF(wkday = 0, day_index, '')) AS 'Mon', MAX(IF(wkday = 1, day_index, '')) AS 'Tue', MAX(IF(wkday = 2, day_index, '')) AS 'Wed', MAX(IF(wkday = 3, day_index, '')) AS 'Thur', MAX(IF(wkday = 4, day_index, '')) AS 'Fri', MAX(IF(wkday = 5, day_index, '')) AS 'Sat', MAX(IF(wkday = 6, day_index, '')) AS 'Sun' FROM ( /* 计算每个日期所在的队、月份、周、星期几*/ SELECT FLOOR((MONTH(day_m) - 1) / 3) AS flag, MONTH(day_m) AS m, WEEK(day_m) AS wk, WEEKDAY(day_m) AS wkday, DAY(day_m) AS day_index, day_m AS full_day FROM ( /* 生成一年的日期 */ SELECT DATE_ADD(first_day, INTERVAL id - 1 DAY) AS day_m FROM ( /* 设定年初第一天和年末最后一天的日期 */ SELECT STR_TO_DATE( CONCAT(YEAR(@someday), '-01-01'), '%Y-%m-%d' ) AS first_day, STR_TO_DATE( CONCAT(YEAR(@someday), '-12-31'), '%Y-%m-%d' ) AS last_day_year) a, t_seq t WHERE t.id <= 1+ DATEDIFF(last_day_year, first_day)) b) c GROUP BY flag, m, wk) d, (SELECT @month := 1, @week := 0, @wk_month := 0) t WHERE 1 = 1) e GROUP BY flag, row_no
输出的效果图,我用蓝色的画笔圈出了月份。
说些不足的地方,SQL 写了一坨,理解起来会有点费劲,这也和使用的数据库工具有关系。我使用的 MySQL 5.6 版本,如果在该版本里面就支持使用一些新语法、函数,结果会更好。
-
使用 with x as()
语法,将每一步做的工作清晰地呈现出来; - 使用开窗函数。用会话变量的方式实现了开窗函数显得比较笨拙,且更复杂;
- 支持动态行转列。
- 用SPSS做数据分析?先弄懂SPSS的基础知识吧
- 学习笔记CB001:NLTK库、语料库、词概率、双连词、词典
- 时序列数据库武斗大会之 OpenTSDB 篇
- 应当使用 SQLite 的五个原因
- Apache Spark作为编译器:深入介绍新的Tungsten执行引擎
- DC/OS 的安装与部署
- Go语言实践:从新手入门到上线真实的小型服务所遇到的那些坑
- 4个简单的数据管理技巧
- MongoDB的设计模式策略
- 如何用容器实现生产级Redis sharding集群一键交付
- Hadoop旧mapreduce的map任务切分原理
- 解读Neo4j全新的Python驱动程序
- MySQL 5.7 X Plugin:流水线技术vs.并行查询技术
- 在下函数式编程,有何贵干?
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- MySQL怎么查看 SQL 的具体执行成本?
- Python 爬虫进阶必备 | 某外卖优惠平台内容加密参数分析
- pytest 自动化测试框架(二)
- Web | Django 与数据库交互,你需要知道的 9 个技巧
- 商机负责人与商机团队负责人不一致时更新团队负责人为商机负责人语句
- mysql常用语句集合(仅供工作日常学习参考)
- 新一代Notebook神器出现,Jupyter危险了!
- vmstat 监视内存使用情况
- Android开发重写Animation实现下拉图片后弹射回去效果示例
- Android 中RxPermissions 的使用方法详解
- Android构建Material Design应用详解
- Android中DrawerLayout实现侧滑菜单效果
- Android获取系统储存以及内存信息的方法(一)
- Android开发实现读取excel数据并保存为xml的方法
- 详解Kotlin 中使用和配置 Dagger2