You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 21:09:01