应避免在where中对字段使用year()、month()等函数,因其导致索引失效;正确做法是用date_format(now(), '%y-%m-01')和last_day(now()) + interval 1 day动态生成范围边界,配合>=和

WHERE 条件里用 YEAR() 和 MONTH() 会出问题
直接写 WHERE YEAR(create_time) = YEAR(NOW()) AND MONTH(create_time) = MONTH(NOW()) 看似合理,但会导致全表扫描——因为对字段加函数会破坏索引。哪怕 create_time 上建了 B+ 树索引,MySQL 也没法用上。
正确做法是算出本月起止时间点,用范围查询:
WHERE create_time >= '2024-06-01' AND create_time <p>这样能走索引,性能差几个数量级。</p> <h3>用 <code>DATE_FORMAT()</code> 或 <code>LAST_DAY()</code> 动态生成边界值</h3> <p>手动写死日期显然不现实。MySQL 提供了可计算的方案:</p>
-
DATE_FORMAT(NOW(), '%Y-%m-01')得到当月第一天(如'2024-06-01') -
LAST_DAY(NOW()) + INTERVAL 1 DAY得到下月第一天(如'2024-07-01')
组合起来就是安全又动态的写法:
WHERE create_time >= DATE_FORMAT(NOW(), '%Y-%m-01')<br> AND create_time <p>注意:用 <code> 而不是 <code>,避免跨月数据被误包含;<code>LAST_DAY()</code> 返回的是当月最后一天的日期(如 <code>'2024-06-30'</code>),加一天才是严格边界。</code></code></p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/ai/991" title="绘蛙AI视频"><img src="https://img.php.cn/upload/ai_manual/001/503/042/68b6cf34a2e8c811.png" alt="绘蛙AI视频" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/ai/991" title="绘蛙AI视频" class="overflowclass">绘蛙AI视频</a> <p class="overflowclass">绘蛙AI视频是一款面向电商营销的图片转视频和模特动态视频生成工具。</p> </div> <a rel="nofollow" href="/ai/991" title="绘蛙AI视频" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <h3>PostgreSQL 或 SQLite 用户别套用 MySQL 写法</h3> <p>不同数据库的日期函数名和行为差异很大:</p>
- PostgreSQL 用
date_trunc('month', now())得本月第一天,date_trunc('month', now()) + interval '1 month'得下月第一天 - SQLite 没有原生月度截断函数,得靠
strftime('%Y-%m-01', 'now'),且要注意它返回的是字符串,比较时隐式转换可能出错 - SQL Server 用
DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1)
跨数据库迁移时,光改函数名不够,还得验证边界是否闭合、时区是否一致。
时区和字段类型不匹配是隐形雷
如果应用写入时用的是 UTC 时间,但数据库服务器或会话时区设为 +08:00,NOW() 返回的就是东八区时间,算出来的“本月”就和业务逻辑对不上。
更隐蔽的是字段类型:若 create_time 是 DATETIME 类型但没存秒级精度,或用了 TIMESTAMP 自动转时区,都可能导致边界判断偏移。
最稳妥的方式是统一在应用层生成起止时间戳(带时区信息),传参进 SQL,而不是依赖数据库函数实时计算。










