codeigniter多条件联表查询需用join()、where()、like()等方法,注意表别名与字段冲突;示例查2024年已支付且商品含“手机”的用户姓名和订单金额,并提供参数绑定、分页、排序及去重的完整实现。

CodeIgniter 中实现多条件联表查询,核心在于合理使用 $this->db->join()、$this->db->where()、$this->db->like() 等方法,并注意表别名、字段冲突和查询顺序。以下以常见业务场景(用户表 + 订单表 + 商品表)为例,提供可直接运行的完整代码(基于 CodeIgniter 3.x,适配 MySQL):
基础多表 JOIN + 多条件 WHERE 查询
查询「2024 年下单、状态为已支付、且商品名称含“手机”的用户姓名与订单金额」:
// 在 Model 中定义方法
public function get_users_orders_goods($year = '2024', $status = 1, $keyword = '手机')
{
$this->db->select('u.name, o.order_no, o.amount, g.title as goods_title');
$this->db->from('users u');
$this->db->join('orders o', 'o.user_id = u.id', 'inner');
$this->db->join('goods g', 'g.id = o.goods_id', 'inner');
// 多条件:年份(时间范围)、订单状态、商品标题模糊匹配
$this->db->where('YEAR(o.create_time)', $year);
$this->db->where('o.status', $status);
$this->db->like('g.title', $keyword);
// 可选:防止 SQL 注入,也可用绑定参数(见下文)
$query = $this->db->get();
return $query->result();
}
带参数绑定的安全写法(推荐)
避免拼接字符串导致注入,用 bind() 或问号占位符:
$sql = "SELECT u.name, o.order_no, g.title
FROM users u
INNER JOIN orders o ON o.user_id = u.id
INNER JOIN goods g ON g.id = o.goods_id
WHERE YEAR(o.create_time) = ?
AND o.status = ?
AND g.title LIKE ?";
$this->db->query($sql, array($year, $status, "%{$keyword}%"));
支持分页 + 排序 + 去重的增强版
实际项目常需分页、按时间倒序、去重用户(同一用户多订单只取一条):
public function get_distinct_user_orders($limit = 10, $offset = 0, $filters = array())
{
$this->db->select('DISTINCT u.id, u.name, MAX(o.amount) as max_amount, COUNT(o.id) as order_count');
$this->db->from('users u');
$this->db->join('orders o', 'o.user_id = u.id', 'left'); // left join 保留无订单用户
if (!empty($filters['status'])) {
$this->db->where('o.status', $filters['status']);
}
if (!empty($filters['start_date'])) {
$this->db->where('o.create_time >=', $filters['start_date']);
}
if (!empty($filters['end_date'])) {
$this->db->where('o.create_time db->group_by('u.id, u.name');
$this->db->order_by('max_amount', 'DESC');
$this->db->limit($limit, $offset);
return $this->db->get()->result();
}
常见问题与避坑提醒
-
字段重名必须加别名:如两个表都有
id,写成u.id、o.id,否则结果集会覆盖 - JOIN 顺序影响性能:把数据量小的表(如状态字典表)放前面,大表(如订单)放后面
-
NULL 值处理:LEFT JOIN 后若用
WHERE o.status = 1,会自动转成 INNER JOIN 效果;应改用AND o.status = 1或WHERE (o.status = 1 OR o.status IS NULL) -
LIKE 模糊查询注意索引:
LIKE '%手机'无法走索引,尽量用LIKE '手机%'











