
本文详解如何在 CodeIgniter 中精准按指定年月(如 2022-01)查询 MySQL 表中所有匹配日期的记录,解决因 like 模糊匹配导致漏查、错查的问题。
本文详解如何在 codeigniter 中精准按指定年月(如 2022-01)查询 mysql 表中所有匹配日期的记录,解决因 `like` 模糊匹配导致漏查、错查的问题。
在 CodeIgniter 开发中,使用表单按年月搜索数据是常见需求。但许多开发者误用 $this->db->like('date', $stotal) 进行日期匹配,这会导致严重逻辑缺陷——LIKE '%2022-01%' 会错误匹配 2022-01-15、2022-01-30,但也可能匹配 2022-011(非法日期)或 2022-01-xx 以外的干扰值(如字段含其他文本时),更关键的是:当 date 字段为 DATE 或 DATETIME 类型时,LIKE 依赖字符串隐式转换,性能差且不可靠,极易遗漏记录。
✅ 正确做法是使用 MySQL 原生日期函数进行精确年月提取与匹配。推荐使用 DATE_FORMAT(date, '%Y-%m'),它将日期字段标准化为 YYYY-MM 格式(如 2022-01),再与传入的 $stotal(如 '2022-01')严格等值比较:
public function searchbilling($stotal) {
$this->db->select('*, SUM(quantity) as quantity');
$this->db->from('delivered');
// ✅ 替换掉不安全的 like,改用 DATE_FORMAT 精确匹配年月
$this->db->where("DATE_FORMAT(date, '%Y-%m') =", $stotal);
$this->db->group_by('YEAR(date), MONTH(date), customer');
$query = $this->db->get();
return $query->result();
}
? 重要注意事项:
- 确保数据库中 date 字段类型为 DATE、DATETIME 或 TIMESTAMP;若为 VARCHAR 存储日期,请先统一格式并考虑迁移为原生日期类型,否则 DATE_FORMAT 可能失效;
- GROUP BY 中的 YEAR(date), MONTH(date), customer 是合理的,但需确认 customer 字段存在且非 NULL,避免分组异常;
- 为提升查询性能,建议在 date 字段上建立普通索引(ALTER TABLE delivered ADD INDEX idx_date (date);),MySQL 在使用 DATE_FORMAT() 时仍可利用索引(尤其在 5.7+ 版本中配合生成列或函数索引效果更佳);
- 安全增强:控制器中应对 $month 和 $year 做基础校验,例如:
$month = $this->input->post('month'); $year = $this->input->post('year'); if (!in_array($month, range('01','12')) || !is_numeric($year) || $year date('Y')) { show_404(); } $stotal = sprintf('%d-%s', $year, $month); // 确保格式为 YYYY-MM
? 扩展建议:若需支持跨月范围搜索(如“2022年1月至3月”),可改用 BETWEEN + STR_TO_DATE() 构造起止时间,例如:
$start = $this->db->escape($year . '-' . $month . '-01');
$end = $this->db->escape(date('Y-m-t', strtotime($year . '-' . $month . '-01')));
$this->db->where("date BETWEEN $start AND $end");
通过采用 DATE_FORMAT() 替代 like,你将获得稳定、高效、符合 SQL 最佳实践的日期筛选能力,彻底解决搜索结果不全的问题。











