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

Laravel分组Eloquent集合:如何获取每组精确3条视频数据

解决Laravel分组后每个分类取N条数据的问题

嘿,我完全懂你的困扰——直接在查询末尾加take(3)只会把整个结果集限制到3条,根本不是你想要的每个分类组里取3条视频。这里有两个实用的解决方案,你可以根据自己的场景选:

方法一:利用Collection的map处理分组后的数据

这是最直接的方式,既然你已经通过groupBy得到了按分类分组的集合,只需要遍历每个分组,对每个分组内的视频集合调用take(3)就行:

private function getHomePageVideos($lang = 'en') {
    return \DB::table('videos')
        ->leftJoin('categories', 'categories.id','=','videos.category_id')
        ->select('videos.*', 'categories.title_' . $lang . ' as category', 'categories.slug as category_slug')
        ->get()
        ->groupBy('category')
        // 遍历每个分类组,只保留每组的前3条视频
        ->map(fn($group) => $group->take(3));
}

这个方法的优点是代码简单易读,适合数据量不大的场景,不需要改动底层查询逻辑。

方法二:数据库层面用窗口函数过滤(更高效)

如果你的视频数据量很大,先把所有数据查出来再处理会浪费内存,这时候可以用数据库的窗口函数(MySQL 8.0+、PostgreSQL等支持),在查询阶段就直接筛选出每个分类的前3条数据:

private function getHomePageVideos($lang = 'en') {
    return \DB::table(function ($query) use ($lang) {
        $query->from('videos')
            ->leftJoin('categories', 'categories.id', '=', 'videos.category_id')
            ->select(
                'videos.*',
                'categories.title_' . $lang . ' as category',
                'categories.slug as category_slug',
                // 按category_id分组,给每个分类下的视频编号(这里按id倒序,你可以改成自己的排序规则)
                \DB::raw('ROW_NUMBER() OVER (PARTITION BY videos.category_id ORDER BY videos.id DESC) as row_num')
            );
    }, 'ranked_videos')
    // 只保留每个分类的前3条
    ->where('row_num', '<=', 3)
    ->get()
    ->groupBy('category');
}

这里用ROW_NUMBER()窗口函数给每个分类下的视频按指定顺序(比如id倒序,也就是最新的在前)编号,然后只取编号≤3的记录,最后再分组。这种方式能大幅减少数据库返回的数据量,性能更好。

你可以根据自己的数据库版本和数据规模选择合适的方法,试试吧!

内容的提问来源于stack exchange,提问作者Tigran.S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:23:19