背景
微信技(mo)術(shù)(yu)群里看到一張圖片, 是考察
MySQL
的知識(shí)點(diǎn). 掃了一眼, 很簡(jiǎn)單啊 ! 實(shí)戰(zhàn)下吧...尷尬了PHP
的時(shí)間日期轉(zhuǎn)換會(huì)用, 發(fā)現(xiàn)MySQL
的日期時(shí)間轉(zhuǎn)換想不起來(lái)了...
知識(shí)回顧
獲取當(dāng)前日期時(shí)間
-
獲得當(dāng)前日期+時(shí)間 (date + time) 函數(shù):
now()
;mysql> select now(); +---------------------+ | now() | +---------------------+ | 2021-08-02 17:30:28 | +---------------------+ 1 row in set (0.00 sec)
-
獲取當(dāng)前日期+時(shí)間 (date + time) 函數(shù):
sysdate()
;sysdate()
日期函數(shù)和now()
類似, 不同之處在于:now()
在執(zhí)行開(kāi)始的時(shí)候就得到值了,sysdate()
在函數(shù)執(zhí)行時(shí)動(dòng)態(tài)得到的值. 舉個(gè)栗子: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)
-
獲取當(dāng)前時(shí)間函數(shù):
current_timestamp
,current_timestamp()
current_timestamp
,current_timestamp()
結(jié)果是一致的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)
日期轉(zhuǎn)換函數(shù), 時(shí)間轉(zhuǎn)換函數(shù)
-
日期/時(shí)間轉(zhuǎn)字符串函數(shù):
date_format(date, format)
,time_format(time, format)
# date_format 可以格式日期和時(shí)間 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 只可以格式時(shí)間 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)
-
字符串轉(zhuǎn)換日期 函數(shù):
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)
轉(zhuǎn)換函數(shù), 可以把一些雜亂無(wú)章的字符串轉(zhuǎn)換為日期格式.
可選參數(shù)
format | 說(shuō)明 |
---|---|
%a | 工作日的縮寫名稱 (Sun..Sat) |
%b | 月份的縮寫名稱 (Jan..Dec) |
%c | 月份, 數(shù)字形式 (0...12) |
%D | 帶有英語(yǔ)后綴的該月日期 (0th, 1st, 2nd,...) |
%d | 該月日期, 數(shù)字形式 (00...31) |
%e | 該月日期, 數(shù)字形式 (0...31) |
%f | 微秒 (000000...999999) |
%H | 小時(shí) (00...23) |
%h | 小時(shí) (01...12) |
%I | 小時(shí) (01...12) |
%i | 分鐘 (00...59) |
%j | 一年中的天數(shù) (0001-366) |
%k | 小時(shí) (0...23) |
%l | 小時(shí) (1..12) |
%M | 月份名稱 (January..December)) |
%m | 月份, 數(shù)字形式 (00..12) |
%p | 上午(AM)或下午( PM) |
%r | 時(shí)間, 12小時(shí)制 (小時(shí)hh:分鐘mm:秒數(shù)ss 后加 AM或PM) |
%S | 秒 (00...59) |
%s | 秒 (00...59) |
%T | 時(shí)間, 24小時(shí)制 (小時(shí)hh:分鐘mm:秒數(shù)ss) |
%U | 周(01...53), 其中周日為每周的第一天; |
%u | 周(01...53), 其中周一為每周的第一天; |
%V | 周(01...53), 其中周日為每周的第一天; 和 %X 同時(shí)使用 |
%v | 周(01...53), 其中周一為每周的第一天; 和 %x 同時(shí)使用 |
%W | 工作日名稱 (周日...周六) |
%w | 一周的每日 (0 = 周日 ... 6 = 周六) |
%X | 該周的年份, 其中周日為每周的第一天, 數(shù)字形式; 和 %V 同時(shí)使用 |
%x | 該周的年份, 其中周一為每周的第一天, 數(shù)字形式; 和 %v 同時(shí)使用 |
%Y | 年份, 數(shù)字形式 (4位數(shù)) |
%y | 年份, 數(shù)字形式 (2位數(shù)) |
%% | '%'文字字符 |
-
日期, 天數(shù)轉(zhuǎn)換函數(shù):
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()
可以看出來(lái)
to_days()
函數(shù), 返回的是一個(gè)天數(shù)!從年份 0 開(kāi)始的天數(shù)
-
時(shí)間, 秒 轉(zhuǎn)換函數(shù):
time_to_sec(time)
,sec_to_time(seconds)
# 時(shí)間轉(zhuǎn)換成秒 mysql> select time_to_sec('00:00:09'); +-------------------------+ | time_to_sec('00:00:09') | +-------------------------+ | 9 | +-------------------------+ 1 row in set (0.00 sec) # 秒轉(zhuǎn)換成時(shí)間 mysql> select sec_to_time(9); +----------------+ | sec_to_time(9) | +----------------+ | 00:00:09 | +----------------+ 1 row in set (0.00 sec)
兩個(gè)函數(shù)是相互的
-
設(shè)定日期, 時(shí)間函數(shù):
makedate(year, dayfoyear)
,maketime(hour, minute, second)
# makedate(); 第二個(gè)參數(shù)是一年中第 ? 天 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)
-
時(shí)間戳, 日期轉(zhuǎn)換函數(shù):
unix_timestamp()
,unix_timestamp(date)
,from_unixtime(unix_timestamp)
,from_unixtime(unix_timestamp, format)
# 當(dāng)前時(shí)間戳 mysql> select unix_timestamp(); +------------------+ | unix_timestamp() | +------------------+ | 1627956774 | +------------------+ 1 row in set (0.01 sec) # 指定時(shí)間的時(shí)間戳 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) # 時(shí)間戳轉(zhuǎn)換成日期 mysql> select from_unixtime(1599624000); +---------------------------+ | from_unixtime(1599624000) | +---------------------------+ | 2020-09-09 12:00:00 | +---------------------------+ 1 row in set (0.00 sec) # 時(shí)間戳轉(zhuǎn)換成指定格式日期 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)
日期時(shí)間計(jì)算函數(shù)
-
日期增加一個(gè)時(shí)間間隔函數(shù):
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) # 增加一小時(shí) 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()
函數(shù), 可以用 date_add() 來(lái)替代.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)
-
為指定日期減去一個(gè)時(shí)間間隔函數(shù):
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)
-
兩個(gè)日期, 時(shí)間相減函數(shù): date(date1, date2), timediff(time1, time2)
# 日期相減, 返回天數(shù) mysql> select datediff('2020-09-09', '2020-09-01'); +--------------------------------------+ | datediff('2020-09-09', '2020-09-01') | +--------------------------------------+ | 8 | +--------------------------------------+ 1 row in set (0.00 sec) # 時(shí)間相減, 返回時(shí)間差值 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()
函數(shù)的兩個(gè)參數(shù)類型必須相同
-
時(shí)間戳 (timestamp) 轉(zhuǎn)換, 增加, 減少函數(shù):
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), 返回結(jié)果以天為單位 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) # 返回結(jié)果以小時(shí)為單位 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()
函數(shù)就比datediff()
功能強(qiáng)多了,datediff()
只能計(jì)算兩個(gè)日期(date)之間相差的天數(shù)
時(shí)區(qū) (timezone) 轉(zhuǎn)換
-
時(shí)區(qū)轉(zhuǎn)換函數(shù):
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)
-
也可以通過(guò)
date_add()
,date_sub()
,timestampadd()
來(lái)實(shí)現(xiàn)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)
解決思路
知識(shí)點(diǎn)回顧了, 再來(lái)解決問(wèn)題
寫出當(dāng)月分組統(tǒng)計(jì)每個(gè)用戶的成績(jī)總和的 SQL 語(yǔ)句
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);
如何優(yōu)化表和 SQL
對(duì)于優(yōu)化數(shù)據(jù)表, 有很多種方式.
但從目前圖里的這個(gè)表, 目前只能想到在 name
, created
字段添加索引
希望有更好答案的 大帥筆, 大漂亮 多多指點(diǎn)下
總結(jié)
MySQL 時(shí)間各種形式轉(zhuǎn)換, 不難, 也不復(fù)雜.
需要經(jīng)常使用, 長(zhǎng)時(shí)間不用, 容易忘記...