当前位置:首页 > 问答 > 正文

MySQL里那些处理时间的函数,怎么用才不迷糊也能灵活应对各种需求

要想在MySQL里把时间函数用得不迷糊,关键不是死记硬背所有函数,而是先搞清楚你手里有什么“材料”(数据格式),你想做出什么“菜”(最终结果),MySQL处理时间主要有两种“材料”:一种是像 2023-10-25 15:30:00 这样完整的日期时间,另一种是像 2023-10-2515:30:00 这样单独的日期或时间,很多迷糊都源于没分清这两者。

第一,搞清楚基础:获取当前时间。

干任何事都得有个起点,处理时间也一样,MySQL给了你两把好用的“勺子”来舀取当前时间:

  • NOW():这把勺子一舀,得到的是完整的日期和时间,2023-10-25 10:30:15,它反映的是SQL语句开始执行的那个瞬间。
  • CURDATE():这把勺子只舀日期部分,给你 2023-10-25
  • CURTIME():这把勺子只舀时间部分,给你 10:30:15

什么时候用呢?比如你要记录一条用户下单的信息,通常会在数据库里有一个 create_time 字段,这时候用 NOW() 最合适,直接把下单的完整时刻记录下来,如果你只是想查询今天的所有订单,那么用 WHERE order_date = CURDATE() 就比手动写日期更灵活,因为明天再运行这条SQL,它自动就变成查“明天”的订单了。

第二,最常用的操作:从时间里提取零件。

MySQL里那些处理时间的函数,怎么用才不迷糊也能灵活应对各种需求

你拿到一个完整的时间戳,但往往只需要里面的某一部分,比如年份、月份、星期几,这时候别想着自己去截字符串,用MySQL提供的“扳手”和“螺丝刀”。

  • 提取年、月、日:YEAR(NOW()) 给你2023,MONTH(NOW()) 给你10,DAY(NOW()) 给你25。
  • 提取小时、分钟、秒:同理,HOUR(NOW()), MINUTE(NOW()), SECOND(NOW())
  • 一个特别有用的:DAYOFWEEK(NOW()),它返回1代表星期日,2代表星期一……7代表星期六,这对于做按周分析的统计非常方便。

举个例子,领导让你查一下本周三的销售数据,你不需要知道本周三具体是几月几号,可以这么写:WHERE DAYOFWEEK(order_date) = 4。(因为星期三是4)

第三,时间的计算:加减和差值。

这是最容易迷糊的地方,但掌握规律就很简单,计算分两种:给一个时间点加上一段时间间隔,或者计算两个时间点之间差了多久。

MySQL里那些处理时间的函数,怎么用才不迷糊也能灵活应对各种需求

  • 加减法:推荐用 DATE_ADD()DATE_SUB()。 它们的用法很像:DATE_ADD(原始时间, INTERVAL 数量 单位),单位可以是 DAY, MONTH, YEAR, HOUR, MINUTE 等。 计算3天后的日期:DATE_ADD(NOW(), INTERVAL 3 DAY)。 计算1小时前的时刻:DATE_SUB(NOW(), INTERVAL 1 HOUR)。 你也可以用简单的加减号 + INTERVALNOW() + INTERVAL 30 MINUTE,效果一样,关键是记住 INTERVAL ... 这个固定搭配。

  • 计算差值:用 DATEDIFF()TIMESTAMPDIFF()DATEDIFF(时间1, 时间2) 专门计算两个日期之间相差的天数,它只关心日期部分,忽略时间。DATEDIFF('2023-10-25', '2023-10-20') 结果是5。 如果你想算得更精确,比如相差多少小时、多少分钟,就要用 TIMESTAMPDIFF(单位, 时间1, 时间2),注意这里的参数顺序,它是用“时间2”减去“时间1”,比如计算两个时间点相差多少小时:TIMESTAMPDIFF(HOUR, '2023-10-25 10:00:00', '2023-10-25 15:30:00') 结果是5(虽然差了5小时30分,但小时部分只算5小时),如果要算分钟,就把单位改成 MINUTE

第四,格式化输出:把时间变成你想要的字符串样子。

数据库里存的时间格式是固定的,但展示给用户看的时候可能需要变个样子,比如把 2023-10-25 显示成 2023年10月25日,或者只显示月份和日期,这就是 DATE_FORMAT() 函数的用武之地。

MySQL里那些处理时间的函数,怎么用才不迷糊也能灵活应对各种需求

这个函数稍微复杂一点,它靠一些特定的符号来代表时间部分:

  • %Y:四位年份
  • %m:两位月份(01-12)
  • %d:两位日期(01-31)
  • %H:24小时制的小时(00-23)
  • %i:分钟(00-59)
  • %s:秒(00-59)
  • %W:星期名(如 Tuesday)

用法是 DATE_FORMAT(时间, '格式字符串')DATE_FORMAT(NOW(), '%Y年%m月%d日') 输出 2023年10月25日DATE_FORMAT(NOW(), '%H:%i:%s') 输出类似 15:30:15,相当于只取时间部分。

实战一下,灵活应对:

假设有个需求:“查询上个月所有订单,并按周分组统计订单金额,显示格式为‘第X周’”。

思路拆解:

  1. 确定时间范围:上个月,我们可以用 DATE_SUB(NOW(), INTERVAL 1 MONTH) 得到上个月的这个时刻,但我们需要的是整个月,所以可以组合使用:上个月的年份和月份。WHERE YEAR(order_date) = YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH)) AND MONTH(order_date) = MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH))
  2. 按周分组:MySQL有 WEEK() 函数,返回一年中的第几周,所以分组条件可以用 GROUP BY WEEK(order_date)
  3. 格式化显示WEEK() 返回的是数字,我们想显示“第X周”,这里可以用字符串连接函数 CONCAT(),写成 CONCAT('第', WEEK(order_date), '周')

最终SQL可能长这样:

SELECT
    CONCAT('第', WEEK(order_date), '周') AS 周次,
    SUM(amount) AS 总金额
FROM orders
WHERE YEAR(order_date) = YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH))
  AND MONTH(order_date) = MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH))
GROUP BY WEEK(order_date);

不迷糊的秘诀就是:先明确你的输入(是什么格式的时间)和输出(想要什么结果),然后像搭积木一样,用上面这些基础函数去组合,多练几次,遇到复杂需求先拆解成“取零件”、“做计算”、“改格式”这些基本步骤,自然就灵活了。