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

Laravel使用Eloquent/DB门面或MongoDB查询按group_id取每组首行并分页

方案1:MySQL/PostgreSQL等关系型数据库实现

方法1:Eloquent关联子查询(推荐,性能更优)

假设对应表的模型名为Post,默认按id升序取每个group_id的第一条记录,写法如下:

// 子查询:获取每个group_id对应的最小id(即第一条记录的id)
$subQuery = Post::selectRaw('MIN(id) as min_id')
    ->groupBy('group_id');

// 主查询关联子查询获取完整记录,直接调用paginate实现分页
$records = Post::joinSub($subQuery, 'group_min', function ($join) {
    $join->on('posts.id', '=', 'group_min.min_id');
})
->orderBy('posts.id') // 可自定义全局排序规则
->paginate(10); // 自定义每页展示条数

如果「第一条记录」的判定规则不是id升序,比如按创建时间最早,将子查询的MIN(id)改为MIN(created_at),同步调整关联条件即可。

方法2:DB门面原生查询

逻辑和Eloquent方案一致,用DB门面实现的写法:

$subQuery = DB::table('posts')
    ->selectRaw('MIN(id) as min_id')
    ->groupBy('group_id');

$records = DB::table('posts')
    ->joinSub($subQuery, 'group_min', 'posts.id', '=', 'group_min.min_id')
    ->orderBy('posts.id')
    ->paginate(10);

方案2:MongoDB数据库实现(基于jenssegers/laravel-mongodb扩展)

用MongoDB聚合查询实现分组取首条,配合手动生成分页实例:

$pageSize = 10;
$currentPage = request('page', 1);

// 聚合查询获取当前页数据
$records = Post::raw(function ($collection) use ($pageSize, $currentPage) {
    return $collection->aggregate([
        // 先按分组内排序规则排序,示例为按id升序
        ['$sort' => ['_id' => 1]],
        // 按group_id分组,取每组第一条完整记录
        ['$group' => [
            '_id' => '$group_id',
            'origin_data' => ['$first' => '$$ROOT']
        ]],
        // 展开数据为原表字段结构
        ['$replaceRoot' => ['newRoot' => '$origin_data']],
        // 分页逻辑
        ['$skip' => ($currentPage - 1) * $pageSize],
        ['$limit' => $pageSize]
    ]);
});

// 生成Laravel标准分页实例,支持前端直接调用links()渲染
$total = Post::distinct('group_id')->count();
$records = new \Illuminate\Pagination\LengthAwarePaginator(
    $records,
    $total,
    $pageSize,
    $currentPage,
    ['path' => request()->url()]
);

内容的提问来源于stack exchange,提问作者Mehdi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:54:03