CodeIgniter如何用单查询实现带Limit与无Limit的分页?
优化CodeIgniter分页查询:单逻辑复用实现总数+分页数据
这确实是个很实用的优化需求——避免重复执行几乎一样的查询,还能复用逻辑。在CodeIgniter里,我们有两种靠谱的方案来实现你的需求:
方案一:MySQL专属高效方案(推荐,仅一次核心查询逻辑)
利用MySQL的SQL_CALC_FOUND_ROWS和FOUND_ROWS()特性,让数据库在执行分页查询的同时,计算出不带LIMIT的总记录数,不需要重复跑一遍WHERE条件。
优化后的代码如下:
// 构建核心查询逻辑(复用你原有的所有条件) $this->db->select('SQL_CALC_FOUND_ROWS *'); // 关键:添加SQL_CALC_FOUND_ROWS标记 if (!empty($id)) { $this->db->where("id", $id); } if (!empty($to)) { $this->db->where("to", $to); } if ($is_deleted != "") { $this->db->where("is_deleted", $is_deleted); } if (!empty($from)) { $this->db->where("from", $from); } if (!empty($priority)) { $this->db->where("priority", $priority); } $this->db->order_by($orderby, $order); // 处理分页参数(保持你原有的逻辑) if ($page < 1) { $page = 1; } if ($pagesize < 1) { $pagesize = 1; } $offset = ($page - 1) * $pagesize; // 1. 执行带LIMIT的查询,获取分页数据 $rows = $this->db->get($this->Table, $pagesize, $offset)->result_array(); // 2. 获取不带LIMIT的总记录数(复用前面查询的计算结果) $total_result = $this->db->query('SELECT FOUND_ROWS() AS total_records')->row(); $total_records = $total_result->total_records;
原理说明:
SQL_CALC_FOUND_ROWS:告诉MySQL在执行当前带LIMIT的查询时,额外计算如果移除LIMIT会返回的总记录数,这个结果会被临时存储。FOUND_ROWS():直接读取刚才存储的总记录数,不需要再重新执行一遍所有WHERE条件的查询,性能提升明显,尤其是当WHERE条件复杂或数据量大时。- 所有查询逻辑(WHERE、ORDER BY)只写一次,后续维护只需要修改一处,避免了两次查询逻辑不一致的风险。
方案二:跨数据库兼容方案(逻辑复用,两次查询)
如果你的项目可能切换到非MySQL数据库(比如PostgreSQL、SQL Server),上面的方案就不适用了。这时候我们可以把查询逻辑封装成私有方法,实现逻辑复用,避免重复写条件:
/** * 封装查询逻辑的私有方法 */ private function buildPaginationQuery() { $this->db->select('*'); if (!empty($id)) { $this->db->where("id", $id); } if (!empty($to)) { $this->db->where("to", $to); } if ($is_deleted != "") { $this->db->where("is_deleted", $is_deleted); } if (!empty($from)) { $this->db->where("from", $from); } if (!empty($priority)) { $this->db->where("priority", $priority); } $this->db->order_by($orderby, $order); } // 主逻辑 // 1. 获取总记录数(false参数表示不重置查询构建器) $this->buildPaginationQuery(); $total_records = $this->db->count_all_results($this->Table, false); // 2. 获取分页数据 $this->buildPaginationQuery(); $rows = $this->db->get($this->Table, $pagesize, $offset)->result_array();
原理说明:
- 把所有查询条件封装到私有方法中,两次查询都调用这个方法,保证逻辑一致。
count_all_results($table, false)中的false参数很关键,它会保留查询构建器中的条件,不会自动重置,这样我们后续可以继续复用相同的条件来查询分页数据。
内容的提问来源于stack exchange,提问作者usman
相关产品推荐
相关产品推荐

