where 时间筛选需注意边界、类型、时区三要素,任一出错即导致数据缺失或错误;正确写法应为 log_time >= '2026-08-01 00:00:00' and log_time
直接用
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,而是字段类型、存储时区、索引结构、查询意图这四者没对齐——随便一个不匹配,时间范围就变成“看起来对,其实漏”。











