Laravel中含JOIN分组DISTINCT的SQL查询如何使用paginate分页
问题原因
DB::select() 执行SQL后返回的是查询结果集合/数组,不是Laravel查询构建器实例,不具备simplePaginate方法,因此你原来的写法无法正常运行。
解决方法
方法1:使用查询构建器构造查询(推荐)
用Laravel查询构建器编写查询逻辑,可直接链式调用分页方法,代码如下:
$data = DB::table('sms_details') ->selectRaw(' destination_tbls.destination, MIN(sms_details.id) as min_sms_id, MIN(sms_details.msg_timestamp) AS timestamp, MIN(destination_tbls.count) as min_count ') // 原SQL里的子查询无过滤条件,可直接关联表无需嵌套 ->join('destination_tbls', 'destination_tbls.id', '=', 'sms_details.destination_tbls_id') ->groupBy('destination_tbls.destination') ->simplePaginate(100);
优化说明:因为已经按
destination_tbls.destination分组,每组仅返回1条记录,因此原SQL里的DISTINCT关键字是多余的,去掉后可提升查询效率。
方法2:原生SQL手动生成分页器
如果你需要保留完整的原生SQL写法,可以手动计算分页偏移量,调用Laravel分页类生成分页对象:
首先引入分页类命名空间:
use Illuminate\Pagination\Paginator;
业务代码如下:
$perPage = 100; // 获取当前页码,默认第1页 $page = request()->input('page', 1); $offset = ($page - 1) * $perPage; // 原生SQL追加分页限制 $sql = " SELECT DISTINCT destination_tbls.destination, MIN(sms_details.id) as min_sms_id, MIN(sms_details.msg_timestamp) AS TIMESTAMP, MIN(destination_tbls.count) as min_count FROM sms_details JOIN (SELECT * FROM destination_tbls) destination_tbls ON destination_tbls.id = sms_details.destination_tbls_id GROUP BY destination_tbls.destination LIMIT ? OFFSET ? "; // 查询当前页数据 $items = DB::select($sql, [$perPage, $offset]); // 生成simplePaginate格式的分页对象 $paginatedData = new Paginator($items, $perPage, $page);
内容的提问来源于stack exchange,提问作者user6580267
相关产品推荐
相关产品推荐

