背景
微信技(mo)术(yu)群里看到一张图片, 是考察
MySQL
的知识点. 扫了一眼, 很简单啊 ! 实战下吧...尴尬了PHP
的时间日期转换会用, 发现MySQL
的日期时间转换想不起来了...
知识回顾
获取当前日期时间
-
获得当前日期+时间 (date + time) 函数:
now()
;mysql> select now(); +---------------------+ | now() | +---------------------+ | 2021-08-02 17:30:28 | +---------------------+ 1 row in set (0.00 sec)
-
获取当前日期+时间 (date + time) 函数:
sysdate()
;sysdate()
日期函数和now()
类似, 不同之处在于:now()
在执行开始的时候就得到值了,sysdate()
在函数执行时动态得到的值. 举个栗子:mysql> select now(), sleep(3), now(); +---------------------+----------+---------------------+ | now() | sleep(3) | now() | +---------------------+----------+---------------------+ | 2021-08-02 17:36:53 | 0 | 2021-08-02 17:36:53 | +---------------------+----------+---------------------+ 1 row in set (3.01 sec) mysql> select sysdate(), sleep(3), sysdate(); +---------------------+----------+---------------------+ | sysdate() | sleep(3) | sysdate() | +---------------------+----------+---------------------+ | 2021-08-02 17:37:24 | 0 | 2021-08-02 17:37:27 | +---------------------+----------+---------------------+ 1 row in set (3.00 sec)
-
获取当前时间函数:
current_timestamp
,current_timestamp()
current_timestamp
,current_timestamp()
结果是一致的mysql> select current_timestamp, current_timestamp(); +---------------------+---------------------+ | current_timestamp | current_timestamp() | +---------------------+---------------------+ | 2021-08-02 17:41:37 | 2021-08-02 17:41:37 | +---------------------+---------------------+ 1 row in set (0.00 sec)
日期转换函数, 时间转换函数
-
日期/时间转字符串函数:
date_format(date, format)
,time_format(time, format)
# date_format 可以格式日期和时间 mysql> select date_format('2021-08-02 17:50:01', '%Y%m%d%H%i%s'); +----------------------------------------------------+ | date_format('2021-08-02 17:50:01', '%Y%m%d%H%i%s') | +----------------------------------------------------+ | 20210802175001 | +----------------------------------------------------+ 1 row in set (0.00 sec) # time_format 只可以格式时间 mysql> select time_format('2021-08-02 17:50:01', '%r'); +------------------------------------------+ | time_format('2021-08-02 17:50:01', '%r') | +------------------------------------------+ | 05:50:01 PM | +------------------------------------------+ 1 row in set (0.00 sec)
-
字符串转换日期 函数:
str_to_date(str, format)
mysql> select str_to_date('09.02.2020', '%m.%d.%Y'); +---------------------------------------+ | str_to_date('09.02.2020', '%m.%d.%Y') | +---------------------------------------+ | 2020-09-02 | +---------------------------------------+ 1 row in set (0.20 sec) mysql> select str_to_date('08.09.2020 08:09:30', '%m.%d.%Y %h:%i:%s'); +---------------------------------------------------------+ | str_to_date('08.09.2020 08:09:30', '%m.%d.%Y %h:%i:%s') | +---------------------------------------------------------+ | 2020-08-09 08:09:30 | +---------------------------------------------------------+ 1 row in set (0.00 sec)
可以看出,
str_to_date(str, format)
转换函数, 可以把一些杂乱无章的字符串转换为日期格式.
可选参数
format | 说明 |
---|---|
%a | 工作日的缩写名称 (Sun..Sat) |
%b | 月份的缩写名称 (Jan..Dec) |
%c | 月份, 数字形式 (0...12) |
%D | 带有英语后缀的该月日期 (0th, 1st, 2nd,...) |
%d | 该月日期, 数字形式 (00...31) |
%e | 该月日期, 数字形式 (0...31) |
%f | 微秒 (000000...999999) |
%H | 小时 (00...23) |
%h | 小时 (01...12) |
%I | 小时 (01...12) |
%i | 分钟 (00...59) |
%j | 一年中的天数 (0001-366) |
%k | 小时 (0...23) |
%l | 小时 (1..12) |
%M | 月份名称 (January..December)) |
%m | 月份, 数字形式 (00..12) |
%p | 上午(AM)或下午( PM) |
%r | 时间, 12小时制 (小时hh:分钟mm:秒数ss 后加 AM或PM) |
%S | 秒 (00...59) |
%s | 秒 (00...59) |
%T | 时间, 24小时制 (小时hh:分钟mm:秒数ss) |
%U | 周(01...53), 其中周日为每周的第一天; |
%u | 周(01...53), 其中周一为每周的第一天; |
%V | 周(01...53), 其中周日为每周的第一天; 和 %X 同时使用 |
%v | 周(01...53), 其中周一为每周的第一天; 和 %x 同时使用 |
%W | 工作日名称 (周日...周六) |
%w | 一周的每日 (0 = 周日 ... 6 = 周六) |
%X | 该周的年份, 其中周日为每周的第一天, 数字形式; 和 %V 同时使用 |
%x | 该周的年份, 其中周一为每周的第一天, 数字形式; 和 %v 同时使用 |
%Y | 年份, 数字形式 (4位数) |
%y | 年份, 数字形式 (2位数) |
%% | '%'文字字符 |
-
日期, 天数转换函数:
to_days(date)
,from_days(days)
# to_days() mysql> select to_days('1970-01-01'); +-----------------------+ | to_days('1970-01-01') | +-----------------------+ | 719528 | +-----------------------+ 1 row in set (0.00 sec) mysql> select to_days('0001-01-01'); +-----------------------+ | to_days('0001-01-01') | +-----------------------+ | 366 | +-----------------------+ 1 row in set (0.00 sec) # from_days()
可以看出来
to_days()
函数, 返回的是一个天数!从年份 0 开始的天数
-
时间, 秒 转换函数:
time_to_sec(time)
,sec_to_time(seconds)
# 时间转换成秒 mysql> select time_to_sec('00:00:09'); +-------------------------+ | time_to_sec('00:00:09') | +-------------------------+ | 9 | +-------------------------+ 1 row in set (0.00 sec) # 秒转换成时间 mysql> select sec_to_time(9); +----------------+ | sec_to_time(9) | +----------------+ | 00:00:09 | +----------------+ 1 row in set (0.00 sec)
两个函数是相互的
-
设定日期, 时间函数:
makedate(year, dayfoyear)
,maketime(hour, minute, second)
# makedate(); 第二个参数是一年中第 ? 天 mysql> select makedate(2021, 91); +--------------------+ | makedate(2021, 91) | +--------------------+ | 2021-04-01 | +--------------------+ 1 row in set (0.00 sec) # maketime(); mysql> select maketime(23, 01, 30); +----------------------+ | maketime(23, 01, 30) | +----------------------+ | 23:01:30 | +----------------------+ 1 row in set (0.00 sec)
-
时间戳, 日期转换函数:
unix_timestamp()
,unix_timestamp(date)
,from_unixtime(unix_timestamp)
,from_unixtime(unix_timestamp, format)
# 当前时间戳 mysql> select unix_timestamp(); +------------------+ | unix_timestamp() | +------------------+ | 1627956774 | +------------------+ 1 row in set (0.01 sec) # 指定时间的时间戳 mysql> select unix_timestamp('2020-09-09 12:00:00'); +---------------------------------------+ | unix_timestamp('2020-09-09 12:00:00') | +---------------------------------------+ | 1599624000 | +---------------------------------------+ 1 row in set (0.00 sec) # 时间戳转换成日期 mysql> select from_unixtime(1599624000); +---------------------------+ | from_unixtime(1599624000) | +---------------------------+ | 2020-09-09 12:00:00 | +---------------------------+ 1 row in set (0.00 sec) # 时间戳转换成指定格式日期 mysql> select from_unixtime(1599624000, '%Y-%D-%M %h:%i:%s'); +------------------------------------------------+ | from_unixtime(1599624000, '%Y-%D-%M %h:%i:%s') | +------------------------------------------------+ | 2020-9th-September 12:00:00 | +------------------------------------------------+ 1 row in set (0.00 sec)
日期时间计算函数
-
日期增加一个时间间隔函数:
date_add()
mysql> set @dt = now(); Query OK, 0 rows affected (0.00 sec) # 增加一天 mysql> select date_add(@dt, interval 1 day); +-------------------------------+ | date_add(@dt, interval 1 day) | +-------------------------------+ | 2021-08-04 11:01:37 | +-------------------------------+ 1 row in set (0.00 sec) # 增加一小时 mysql> select date_add(@dt, interval 1 hour); +--------------------------------+ | date_add(@dt, interval 1 hour) | +--------------------------------+ | 2021-08-03 12:01:37 | +--------------------------------+ 1 row in set (0.00 sec) # 增加一周 mysql> select date_add(@dt, interval 1 week); +--------------------------------+ | date_add(@dt, interval 1 week) | +--------------------------------+ | 2021-08-10 11:01:37 | +--------------------------------+ 1 row in set (0.00 sec) # 增加一季度 mysql> select date_add(@dt, interval 1 quarter); +-----------------------------------+ | date_add(@dt, interval 1 quarter) | +-----------------------------------+ | 2021-11-03 11:01:37 | +-----------------------------------+ 1 row in set (0.00 sec) # 减少一天 mysql> select date_add(@dt, interval -1 day); +--------------------------------+ | date_add(@dt, interval -1 day) | +--------------------------------+ | 2021-08-02 11:01:37 | +--------------------------------+ 1 row in set (0.00 sec)
-
adddate()
,addtime()
函数, 可以用 date_add() 来替代.mysql> set @dt = '2020-08-20 19:30:40'; Query OK, 0 rows affected (0.00 sec) mysql> select date_add(@dt, interval '01:15:30' hour_second); +------------------------------------------------+ | date_add(@dt, interval '01:15:30' hour_second) | +------------------------------------------------+ | 2020-08-20 20:46:10 | +------------------------------------------------+ 1 row in set (0.00 sec) mysql> select date_add(@dt, interval '1 01:12:30' day_second); +-------------------------------------------------+ | date_add(@dt, interval '1 01:12:30' day_second) | +-------------------------------------------------+ | 2020-08-21 20:43:10 | +-------------------------------------------------+ 1 row in set (0.00 sec)
-
为指定日期减去一个时间间隔函数:
date_sub()
mysql> select date_sub('2020-09-09 09:09:00', interval '1 1:1:1' day_second); +----------------------------------------------------------------+ | date_sub('2020-09-09 09:09:00', interval '1 1:1:1' day_second) | +----------------------------------------------------------------+ | 2020-09-08 08:07:59 | +----------------------------------------------------------------+ 1 row in set (0.00 sec)
-
两个日期, 时间相减函数: date(date1, date2), timediff(time1, time2)
# 日期相减, 返回天数 mysql> select datediff('2020-09-09', '2020-09-01'); +--------------------------------------+ | datediff('2020-09-09', '2020-09-01') | +--------------------------------------+ | 8 | +--------------------------------------+ 1 row in set (0.00 sec) # 时间相减, 返回时间差值 mysql> select timediff('2020-09-09 09:00:00', '2020-09-09 00:00:00'); +--------------------------------------------------------+ | timediff('2020-09-09 09:00:00', '2020-09-09 00:00:00') | +--------------------------------------------------------+ | 09:00:00 | +--------------------------------------------------------+ 1 row in set (0.00 sec)
timediff()
函数的两个参数类型必须相同
-
时间戳 (timestamp) 转换, 增加, 减少函数:
timestamp(date)
,timestamp(dt, time)
,timestampadd(unit, interval, datetime_expr)
,timestampdiff(unit, datetime_expr1, datetime_expr2)
# timestamp(date) mysql> select timestamp('2020-09-09'); +-------------------------+ | timestamp('2020-09-09') | +-------------------------+ | 2020-09-09 00:00:00 | +-------------------------+ 1 row in set (0.00 sec) # timestamp(dt, time) mysql> select timestamp('2020-09-09 09:00:00', '01:00:00'); +----------------------------------------------+ | timestamp('2020-09-09 09:00:00', '01:00:00') | +----------------------------------------------+ | 2020-09-09 10:00:00 | +----------------------------------------------+ 1 row in set (0.00 sec) # timestampadd(unit, interval, datetime_expr) mysql> select timestampadd(day, 1, '2020-09-09 09:00:00'); +---------------------------------------------+ | timestampadd(day, 1, '2020-09-09 09:00:00') | +---------------------------------------------+ | 2020-09-10 09:00:00 | +---------------------------------------------+ 1 row in set (0.00 sec) # timestampdiff(unit, datetime_expr1, datetime_expr2), 返回结果以天为单位 mysql> select timestampdiff(day, '2020-09-09', '2020-09-01'); +------------------------------------------------+ | timestampdiff(day, '2020-09-09', '2020-09-01') | +------------------------------------------------+ | -8 | +------------------------------------------------+ 1 row in set (0.00 sec) # 返回结果以小时为单位 mysql> select timestampdiff(hour, '2020-09-09 09:00:00', '2020-09-01 08:00:00'); +-------------------------------------------------------------------+ | timestampdiff(hour, '2020-09-09 09:00:00', '2020-09-01 08:00:00') | +-------------------------------------------------------------------+ | -193 | +-------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select datediff('2020-09-09', '2020-09-01'); +--------------------------------------+ | datediff('2020-09-09', '2020-09-01') | +--------------------------------------+ | 8 | +--------------------------------------+ 1 row in set (0.00 sec)
timestampdiff()
函数就比datediff()
功能强多了,datediff()
只能计算两个日期(date)之间相差的天数
时区 (timezone) 转换
-
时区转换函数:
convert_tz(dt, from_tz, to_tz)
mysql> select convert_tz('2020-09-09 12:00:00', '+08:00', '+00:00'); +-------------------------------------------------------+ | convert_tz('2020-09-09 12:00:00', '+08:00', '+00:00') | +-------------------------------------------------------+ | 2020-09-09 04:00:00 | +-------------------------------------------------------+ 1 row in set (0.00 sec)
-
也可以通过
date_add()
,date_sub()
,timestampadd()
来实现mysql> select date_add('2020-09-09 12:00:00', interval -8 hour); +---------------------------------------------------+ | date_add('2020-09-09 12:00:00', interval -8 hour) | +---------------------------------------------------+ | 2020-09-09 04:00:00 | +---------------------------------------------------+ 1 row in set (0.00 sec) mysql> select date_sub('2020-09-09 12:00:00', interval 8 hour); +---------------------------------------------------+ | date_add('2020-09-09 12:00:00', interval -8 hour) | +---------------------------------------------------+ | 2020-09-09 04:00:00 | +---------------------------------------------------+ 1 row in set (0.00 sec) mysql> select timestampadd(hour, -8, '2020-09-09 12:00:00'); +-----------------------------------------------+ | timestampadd(hour, -8, '2020-09-09 12:00:00') | +-----------------------------------------------+ | 2020-09-09 04:00:00 | +-----------------------------------------------+ 1 row in set (0.00 sec)
解决思路
知识点回顾了, 再来解决问题
写出当月分组统计每个用户的成绩总和的 SQL 语句
select name, sum(score) from A
where
created >= UNIX_TIMESTAMP(FROM_UNIXTIME(UNIX_TIMESTAMP(),'%Y-%m-01 00:00:00'))
and
created <= UNIX_TIMESTAMP(DATE_FORMAT(LAST_DAY(CURDATE()), '%Y-%m-%d 23:59:59'))
group by (name);
如何优化表和 SQL
对于优化数据表, 有很多种方式.
但从目前图里的这个表, 目前只能想到在 name
, created
字段添加索引
希望有更好答案的 大帅笔, 大漂亮 多多指点下
总结
MySQL 时间各种形式转换, 不难, 也不复杂.
需要经常使用, 长时间不用, 容易忘记...