SQL 打印一个月的日历
今天,我们用 SQL 做一件有趣的东西:打印一个月的日历。
下图是我从电脑上截的本月的日历。
接下来我们在 MYSQL 上输出这个效果。
大致的思路如下:
- 获取指定日期所在月份的第一天的日期和该月的天数;
- 生成该月的所有日期集合;
- 格式化输出。
1 获取月初第一天和该月的天数
在 MySQL 里面,实现日期的加减可以使用 DATE_ADD(date,INTERVAL expr unit) / DATE_SUB(date,INTERVAL expr unit)
函数。
另外,还可以用 LAST_DAY(date)
获取最后一天的日期。
# 设置日期变量
SET @someday:=CURDATE();
# 获取该月第一天
SELECT DATE_ADD(@someday,INTERVAL - DAY(@someday) + 1 DAY)
# 获取该月的天数
SELECT DAY(LAST_DAY(@someday))
2 生成所在月的日期集合
MySQL 暂时没有提供像 Oracle 的start with connect by prior
一样的语法,用它可以递归生成一批简单的测试数据集,但我们可以借助数字辅助表实现该功能。
我们用到了数字辅助表 t_seq,t_seq 的表结构很简单,只有一个整数字段,里面存储了从 1 - 1000 的自然数。
t_seq 的表结构
CREATE TABLE `t_seq` (
`id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
生成一个月的所有日期的集合
SELECT
WEEK(day_m, 1) 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
DATE_ADD(
@someday,
INTERVAL - DAY(@someday) + 1 DAY
) AS first_day) a,
t_seq t
WHERE t.id <= DAY(LAST_DAY(@someday))
3 格式化日历
我们在第 2 步生成的数据集只有一列,要输出日历的效果,还得做一层行转列操作:根据每周做分组,星期一到星期天作为列,将一列转成四行七列或者五行七列的格式。
MySQL 提供了 WEEK(date[,mode])
函数获取每周的编号,传入不同的 mode 参数返回的数据会不一样。
Mode |
First day of week |
Range |
Week 1 is the first week … |
---|---|---|---|
0 |
Sunday |
0-53 |
with a Sunday in this year |
1 |
Monday |
0-53 |
with 4 or more days this year |
2 |
Sunday |
1-53 |
with a Sunday in this year |
3 |
Monday |
1-53 |
with 4 or more days this year |
4 |
Sunday |
0-53 |
with 4 or more days this year |
5 |
Monday |
0-53 |
with a Monday in this year |
6 |
Sunday |
1-53 |
with 4 or more days this year |
7 |
Monday |
1-53 |
with a Monday in this year |
由于我们把星期一看作一周的第一天,所以 mode 只能选 1 和 5。
完整的 SQL 实现如下:
SET @someday := CURDATE();
SELECT
MAX(IF(wkday = 0, day_index, '')) AS '一',
MAX(IF(wkday = 1, day_index, '')) AS '二',
MAX(IF(wkday = 2, day_index, '')) AS '三',
MAX(IF(wkday = 3, day_index, '')) AS '四',
MAX(IF(wkday = 4, day_index, '')) AS '五',
MAX(IF(wkday = 5, day_index, '')) AS '六',
MAX(IF(wkday = 6, day_index, '')) AS '日'
FROM
(SELECT
WEEK(day_m, 1) 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
DATE_ADD(
@someday,
INTERVAL - DAY(@someday) + 1 DAY
) AS first_day) a,
t_seq t
WHERE t.id <= DAY(LAST_DAY(@someday))) b) c
GROUP BY wk
最终的效果图
- dedecms文章页调用地址(当前文章URL)如何操作?
- 饭团开通一周,3人学会了比特币操作
- Sample K算法
- C#读取“我的文档”等特殊系统路径及环境变量
- winform CheckedListBox实现全选/全不选
- 机器学习该如何入门
- dedecms建的网站如何去掉/index.html
- WPF ContextMenu的使用
- Json的序列化与反序列化以及乱入的k_BackingField
- 亚马逊面试题
- VisualStudio 怎么使用Visual Leak Detector
- Cannot find module 'socket.io'
- 【学术】独热编码如何在Python中排列数据?
- 比特币的私钥【区块链生存训练】
- 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 实例讲解