之前,已经向大家介绍了一些mysql的常用日期函数https://www.jianshu.com/p/93251dbc7278
以及使用这些函数实现的稍复杂的日期查询https://www.jianshu.com/p/bcfd72967681
本次将在日期函数的组合使用上,加强逻辑复杂性,要实现的查询目标为:
查找当前月份的第一个和最后一个星期一
基本逻辑为:
①查找当前月份的第一天
②若第一天为星期五,则返回当前月份;若>星期一,为(星期二到星期六)则查找下周的星期一;若第一天为星期天,则在第一天基础上加一天即为星期一;
需要注意的是,在dayofweek()函数中,星期天=1,星期一=2.......
③在第一个星期一基础上加28天,如果还在该月之内,则为最后一个星期一;如果已经不在该月,则在第一个星期一基础上加21,即可得该月最后一个星期一;
首先查找当前月份的第一天
mysql> select date_add(
-> date_add(current_date(),interval -day(current_date()) day),
-> interval 1 day) as first_day,
-> month(current_date()) as current_month;
+------------+---------------+
| first_day | current_month |
+------------+---------------+
| 2018-10-01 | 10 |
+------------+---------------+
1 row in set (0.01 sec)
解析:内部date_add(current_date(),interval -day(current_date()) day) 表示当前日期减去当前处于该月的第几天,可求得上月的最后一天;
date_add(
-> date_add(current_date(),interval -day(current_date()) day),
-> interval 1 day) as first_day
在上月最后一天的基础上加1,即可求得当前月份的第一天。
接下来查找当前月份的第一个星期一:
这里涉及到几个函数,首先为大家介绍一下
case when end是一个条件函数,可通过设置多个条件限定返回值;
sign(expr) 当expr==0,则sign()返回0,expr>0,sign()返回1,expr<0,sign() 返回-1;
mysql> select case sign(dayofweek(first_day)-2)
-> when 0 then first_day
-> when -1 then date_add(first_day,interval 1 day)
-> when 1 then date_add(first_day,interval (7-(dayofweek(first_day)-2)) day)
-> end as first_monday , current_month
-> from (
-> select date_add(
-> date_add(current_date(),interval -day(current_date()) day),
-> interval 1 day) as first_day,
-> month(current_date()) as current_month)a;
+--------------+---------------+
| first_monday | current_month |
+--------------+---------------+
| 2018-10-01 | 10 |
+--------------+---------------+
1 row in set (0.00 sec)
解析:
从内向外看,在第一步中我们获取了当月第一天first_day和当前月份current_month;
由于dayofweek(星期一)取值为2,因此在case when函数中,首先判断,
~~若dayofweek(first_day)-2=0,则代表first_day为第一个星期一;
~~若dayofweek(first_day)-2<0,只有一种可能,dayofweek(first_day)=1,即本月第一天为星期天,在此基础上加1则是本月第一个星期一为:date_add(first_day,interval 1 day);
~~若dayofweek(first_day)-2>0,先计算当前日期距离星期一有几天dayofweek(first_day)-2),再用7减去差值,可得距离下周的星期一有几天,在本月第一天的基础上加上这个差值即可date_add(first_day,interval (7-(dayofweek(first_day)-2)) day);
最后求本月的最后一个星期一:
mysql> select first_monday,
-> case month(date_add(first_monday,interval 28 day))
-> when current_month then date_add(first_monday,interval 28 day)
-> else date_add(first_monday,interval 21 day)
-> end as last_monday
-> from(
-> select case sign(dayofweek(first_day)-2)
-> when 0 then first_day
-> when -1 then date_add(first_day,interval 1 day)
-> when 1 then date_add(first_day,interval (7-(dayofweek(first_day)-2)) day)
-> end as first_monday , current_month
-> from (
-> select date_add(
-> date_add(current_date(),interval -day(current_date()) day),
-> interval 1 day) as first_day,
-> month(current_date()) as current_month
-> )a
-> )b;
+--------------+-------------+
| first_monday | last_monday |
+--------------+-------------+
| 2018-10-01 | 2018-10-29 |
+--------------+-------------+
1 row in set (0.00 sec)
解析:
一个月最多有四个完整周
当本月第一个星期一加上28仍在本月内时,即可得最后一个星期一;
当本月第一个星期一加上28不在本月内时,则上周的星期一为本月最后一个星期一;
网友评论