如何使用Laravel Eloquent查询created_at列匹配指定年月的记录
为什么你当前的查询查不到结果
Laravel 模型默认自动维护的created_at字段是带时分秒的完整datetime格式,数据库实际存储的值类似2020-10-15 09:32:17。你写的where('created_at', '=', '2020-10')是在做整字段等值匹配,纯年月字符串和完整datetime值完全不相等,所以永远拿不到匹配的记录。
可选实现方案
按查询性能优先级排序,可根据业务场景选择对应写法:
- 索引友好的范围查询(推荐大表场景使用)
利用Carbon构造目标年月的时间边界,通过范围匹配查询,不会对字段做函数处理,能正常命中created_at列的索引:use Carbon\Carbon; $targetMonth = '2020-10'; // 计算目标月的起始、结束时间 $monthStart = Carbon::createFromFormat('Y-m', $targetMonth)->startOfMonth(); $monthEnd = Carbon::createFromFormat('Y-m', $targetMonth)->endOfMonth(); School::where('user_id', 1) ->whereBetween('created_at', [$monthStart, $monthEnd]) ->count(); - Eloquent内置方法查询(小数据量场景使用)
直接使用查询构造器自带的whereYear、whereMonth方法组合匹配对应年月,不需要手动处理时间计算:
注意:该方法底层会对School::where('user_id', 1) ->whereYear('created_at', '2020') ->whereMonth('created_at', '10') ->count();created_at字段套日期截取函数,无法直接命中普通索引,表数据量超过百万级时查询性能会明显下降。 - 原生日期格式匹配(临时查询场景使用)
直接通过原生SQL对字段做格式化后匹配年月,适合小数据量的临时调试场景:
注意:和上面的内置方法一致,字段函数处理会导致索引失效,不适合大表线上查询。School::where('user_id', 1) ->whereRaw("DATE_FORMAT(created_at, '%Y-%m') = '2020-10'") ->count();
内容的提问来源于stack exchange,提问作者shekwo
相关产品推荐
相关产品推荐

