必须用TIMESTAMPDIFF而非DATEDIFF:当需秒/分/小时/月/年等任意单位,或DATETIME/TIMESTAMP含时间部分影响逻辑时;DATEDIFF仅算日历天数,忽略时间,如'2026-07-01 23:59:59'与'2026-07-01 00:00:01'返回0,而TIMESTAMPDIFF(HOUR,...)返回23。

直接用 TIMESTAMPDIFF,别硬套 DATEDIFF——除非你明确只要“日历天数”且能接受忽略时间部分。
什么时候必须用 TIMESTAMPDIFF 而不是 DATEDIFF
当你需要秒、分钟、小时、月、年等任意单位,或字段类型是 DATETIME/TIMESTAMP 且时间部分影响业务逻辑时,DATEDIFF 就不够用了。
-
DATEDIFF('2026-07-01 23:59:59', '2026-07-01 00:00:01')返回0,因为它只取日期部分;而实际相差近 24 小时 -
TIMESTAMPDIFF(HOUR, '2026-07-01 00:00:01', '2026-07-01 23:59:59')返回23,符合预期 - 想查“超时未支付订单(30 分钟)”,必须用
TIMESTAMPDIFF(MINUTE, created_at, NOW()) > 30,不能用DATEDIFF
TIMESTAMPDIFF 的参数顺序和单位写法容易错
它固定是 TIMESTAMPDIFF(unit, start, end),结果 = end - start;单位必须大写且拼写准确,否则报错或返回 NULL。
- 常见错误:
TIMESTAMPDIFF(MINUTE, end_time, start_time)—— 顺序反了,结果为负数 - 单位写成小写
minute或错字min,MySQL 直接报错Incorrect arguments to TIMESTAMPDIFF - 支持的单位:
SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER、YEAR(注意没有WEEKDAY或DAYOFMONTH)
在 WHERE 条件里用 TIMESTAMPDIFF 会拖慢查询
只要把日期字段包进函数里,比如 WHERE TIMESTAMPDIFF(DAY, created_at, NOW()) > 7,MySQL 就无法使用 created_at 上的索引,全表扫描不可避免。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 正确写法是把函数移到右边:
WHERE created_at - 同理,
TIMESTAMPDIFF(MONTH, ...)在条件中也得改写为created_at - 如果业务真要按“整月差”过滤(比如“注册满 3 个自然月”),
DATE_SUB更可靠,也走索引
月末日期和跨时区场景下结果不直观
TIMESTAMPDIFF(MONTH, '2026-01-31', '2026-02-28') 返回 0,不是 1;跨时区数据没统一转换时,结果可能偏移一天。
- 本质是它按日历边界计算:先比年份差 ×12 + 月份差,再看“是否已过当月对应日”;2 月 28 日还没到 1 月 31 日的“下个月”,所以不算满 1 个月
- 遇到
'2026-01-31'这类月末日期,MySQL 内部会向下取整(如转成'2026-01-30')再算,行为不可控 - 字段存的是
TIMESTAMP但连接 session 时区是+08:00,而NOW()返回本地时区值,会导致比较偏差——务必用CONVERT_TZ(created_at, '+00:00', @@session.time_zone)对齐
真正难的不是写出函数,而是搞清你要的“差值”到底指什么:是物理时间长度?还是日历上的完整周期?前者用 TIMESTAMPDIFF(SECOND, ...) 最稳,后者得结合业务规则兜底判断。










