WHERE 时间筛选需注意边界、类型、时区三要素,任一出错即导致数据缺失或错误;正确写法应为 log_time >= '2026-08-01 00:00:00' AND log_time < '2026-08-05 00:00:00'。

直接用 WHERE 加时间比较就能筛,但边界写错、类型不匹配、时区没对齐,三条里踩中任意一条,结果就少数据或不对。
WHERE 里用 >= 和
很多人图省事写 BETWEEN '2026-08-01' AND '2026-08-05',但字段是 DATETIME 类型时,它实际等价于 >= '2026-08-01 00:00:00' AND ,会漏掉 8 月 5 日当天其他时间点的数据。
更稳妥的写法是:
WHERE log_time >= '2026-08-01' AND log_time (推荐,左闭右开,不含边界秒级误差)- 如果字段是
DATE类型,BETWEEN可用,但必须确认数据库没把时间部分默认补成00:00:00 - 避免写
'2026-08-05 23:59:59'——MySQL 8.0+ 支持微秒,PostgreSQL 默认带毫秒,硬写秒级字符串容易截断丢失
动态时间范围优先用数据库函数,别拼字符串
查“最近 7 天”“本月第一天”这类需求,手拼日期字符串既难维护又易出错。各库原生函数更可靠:
- MySQL:用
DATE_SUB(NOW(), INTERVAL 7 DAY)替代'2026-07-30' - PostgreSQL:用
NOW() - INTERVAL '7 days',注意单引号和单位复数 - SQL Server:用
DATEADD(day, -7, GETDATE()),别用GETDATE()-7(隐式转换可能出错) - 想查本月第一天?MySQL 写
DATE_FORMAT(NOW(), '%Y-%m-01'),PostgreSQL 写DATE_TRUNC('month', NOW())
时区不一致时,先统一再比较
如果你的表里存的是 UTC 时间(比如日志系统),而业务要求按北京时间(UTC+8)查“今天”,直接用 CURDATE() 就会错。
正确做法是把字段或参数转到同一时区:
- MySQL:用
CONVERT_TZ(log_time, '+00:00', '+08:00')转换字段,再比较 - PostgreSQL:用
log_time AT TIME ZONE 'UTC' AT TIME ZONE 'Asia/Shanghai' - 更优策略是应用层写入时就存本地时间,或统一存 UTC + 显式标注时区,避免每次查询都转换
索引失效常因函数包裹时间字段
写 WHERE DATE(log_time) = '2026-08-05' 看似简洁,但 DATE() 函数会让 log_time 字段上的索引完全失效,大数据量时变全表扫描。
替代方案:
- 用范围查询:
WHERE log_time >= '2026-08-05' AND log_time (能走索引) - 需要按天聚合?
GROUP BY DATE(log_time)不影响查询性能,但 WHERE 里别对字段用函数 - 如果必须用年/月筛选,建表达式索引(MySQL 8.0+ 支持
CREATE INDEX idx_year ON t ((YEAR(log_time))))
真正麻烦的不是写对一行 SQL,而是字段类型、存储时区、索引结构、查询意图这四者没对齐——随便一个不匹配,时间范围就变成“看起来对,其实漏”。

















