Codeigniter limit offset实现降序分页返回空结果问题排查
问题根因
你代码的核心错误是混淆了SQL LIMIT 偏移量和数据ID值的定义:
MySQL 中 LIMIT offset, row_count 语法的第一个参数 offset 指的是从结果集的第 offset + 1 行开始返回数据,不是你以为的「筛选ID小于等于offset的记录」。
你首次查询传入index=10作为偏移量,生成的SQL为LIMIT 10, 5,但你的表总共只有10条数据,排序后的结果集行号范围是0~9,从第11行(偏移量10)开始取数据自然返回空结果。
解决方案
这里提供两种常用的分页实现方式,你可以根据业务场景选择:
方案1:传统页码分页
适合需要展示总页数、支持跳转到指定页的场景,不需要提前查询最大ID:
$limit = 5; // 前端传入当前页码,默认第1页 $current_page = (int)$this->input->get('page', 1); // 计算偏移量:(页码-1)*每页数量 $offset = ($current_page - 1) * $limit; $this->db->select('*'); $this->db->from('participant_videos'); $this->db->order_by('id','DESC'); $this->db->limit($limit, $offset); $query = $this->db->get(); $videos = $query->result_array(); return [ 'videos' => $videos, // 告知前端是否还有下一页 'has_next' => count($videos) === $limit ];
- 第1页查询偏移量为0,返回ID 10、9、8、7、6
- 第2页查询偏移量为5,返回ID 5、4、3、2、1
- 第3页查询返回空,加载结束
方案2:游标分页(推荐用于无限下拉场景)
适合移动端/短视频类的无限下拉加载场景,性能优于传统offset分页,不需要传页码,每次仅需传入上次返回的最小ID:
$limit = 5; // 前端传入上次返回的列表最小ID,首次查询传0即可 $last_min_id = (int)$this->input->get('last_id', 0); $this->db->select('*'); $this->db->from('participant_videos'); // 非首次查询时,只筛选ID小于上次最小ID的记录 if ($last_min_id > 0) { $this->db->where('id <', $last_min_id); } $this->db->order_by('id','DESC'); $this->db->limit($limit); $query = $this->db->get(); $videos = $query->result_array(); // 计算下次查询需要传入的游标:当前返回列表的最小ID $next_last_id = empty($videos) ? 0 : end($videos)['id']; return [ 'videos' => $videos, 'last_id' => $next_last_id ];
- 首次查询返回ID 10、9、8、7、6,返回
last_id=6 - 第二次查询传入
last_id=6,返回ID 5、4、3、2、1,返回last_id=1 - 第三次查询传入
last_id=1,返回空数组,加载结束
内容的提问来源于stack exchange,提问作者failedCoder
相关产品推荐
相关产品推荐

