相关文章推荐
冷静的热带鱼  ·  【jdk1.8】LocalDateTime ...·  2 月前    · 
会开车的钱包  ·  eval() - JavaScript | MDN·  2 月前    · 
乐观的熊猫  ·  时间日期函数操作符详解-云原生数据库 ...·  1 周前    · 
深情的围巾  ·  【攻略】零-刺青之聲-攻略(不算簡易的簡易版 ...·  10 月前    · 
卖萌的登山鞋  ·  hive ...·  1 年前    · 
重情义的鸡蛋  ·  名字:神父受胎 类型:人外 ...·  1 年前    · 
耍酷的自行车  ·  如何使用IntelliJ ...·  2 年前    · 
还单身的牙膏  ·  Fix PostgreSQL ...·  2 年前    · 
Code  ›  SQL 打印一个月的日历开发者社区
date 社区功能 select date函数
https://cloud.tencent.com/developer/article/1664409
愉快的匕首
2 年前
白日梦想家

SQL 打印一个月的日历

腾讯云
开发者社区
文档 建议反馈 控制台
首页
学习
活动
专区
工具
TVP
最新优惠活动
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
白日梦想家
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
社区首页 > 专栏 > SQL 打印一个月的日历

SQL 打印一个月的日历

作者头像
白日梦想家
发布 于 2020-07-20 10:04:30
1.2K 0
发布 于 2020-07-20 10:04:30
举报
文章被收录于专栏: SQL实现 SQL实现

今天,我们用 SQL 做一件有趣的东西:打印一个月的日历。

下图是我从电脑上截的本月的日历。

接下来我们在 MYSQL 上输出这个效果。

大致的思路如下:

  1. 获取指定日期所在月份的第一天的日期和该月的天数;
  2. 生成该月的所有日期集合;
  3. 格式化输出。

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 
    (SELECT 
      DATE_ADD(first_day, INTERVAL id - 1 DAY) AS day_m 
      (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 '日' 
  (SELECT 
    WEEK(day_m, 1) AS wk,
    WEEKDAY(day_m) AS wkday,
    DAY(day_m) AS day_index,
    day_m AS full_day 
    (SELECT 
      DATE_ADD(first_day, INTERVAL id - 1 DAY) AS day_m 
      (SELECT 
        DATE_ADD(
          @someday,
          INTERVAL - DAY(@someday) + 1 DAY
 
推荐文章
冷静的热带鱼  ·  【jdk1.8】LocalDateTime 详细用法,保姆级 - yīyáng
2 月前
会开车的钱包  ·  eval() - JavaScript | MDN
2 月前
乐观的熊猫  ·  时间日期函数操作符详解-云原生数据库 PolarDB-阿里云
1 周前
深情的围巾  ·  【攻略】零-刺青之聲-攻略(不算簡易的簡易版)編排過 @零~ZERO~ 哈啦板 - 巴哈姆特
10 月前
卖萌的登山鞋  ·  hive 正则表达式去除数字_mob64ca12ea4e24的技术博客_51CTO博客
1 年前
重情义的鸡蛋  ·  名字:神父受胎 类型:人外 涩程度:⭐⭐⭐⭐(第一次看这种类型的,请轻易尝试,我怕你被吓着了)_哔哩哔哩_bilibili
1 年前
耍酷的自行车  ·  如何使用IntelliJ IDEA開發AEM專案 | Adobe Experience Manager
2 年前
还单身的牙膏  ·  Fix PostgreSQL connection refused easily
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号