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

如何在Laravel Eloquent中为指定分类的每个场所获取3个分支

解决方案

你的核心问题是原查询直接通过LEFT JOIN关联了所有分支,导致每个场所的所有分支都会被返回,且结果是场所与分支的笛卡尔积(同一场所会对应多条分支记录)。要实现指定分类下每个场所仅返回最多3个分支,可以用以下几种方式:

方法1:利用Eloquent关联预加载(推荐,符合Laravel最佳实践)

首先确保你的Place模型已经定义了与Branch的关联:

// app/Models/Place.php
public function branches()
{
    return $this->hasMany(Branch::class, 'place_id');
}

然后通过预加载并限制分支数量来查询:

$places = Place::select(
        'places.id as place_id',
        'places.name',
        'places.description',
        'places.tags as place_tags',
        'categories.id as category_id',
        'categories.name'
    )
    ->join('categories', 'categories.id', '=', 'places.category_id')
    // 预加载每个场所的最多3个分支,同时重写字段名
    ->with(['branches' => function ($query) {
        $query->select('id as branch_id', 'name as branch_name', 'place_id')
              ->limit(3);
    }])
    ->whereIn('places.category_id', [1, 2, 3])
    ->get();

这种方式返回的结果中,每个Place对象会包含一个branches集合,里面最多3个分支数据,结构更清晰。

方法2:使用窗口函数(适合需要扁平化结果的场景)

如果你的数据库支持窗口函数(如MySQL 8.0+、PostgreSQL),可以通过子查询给每个场所的分支编号,再筛选出前3个:

$places = DB::select("
    SELECT 
        p.id as place_id,
        p.name,
        p.description,
        p.tags as place_tags,
        b.id as branch_id,
        b.name as branch_name,
        c.id as category_id,
        c.name
    FROM places p
    LEFT JOIN categories c ON c.id = p.category_id
    LEFT JOIN (
        -- 给每个场所的分支按ID排序并编号
        SELECT *,
               ROW_NUMBER() OVER (PARTITION BY place_id ORDER BY id) as rn
        FROM branches
    ) b ON b.place_id = p.id AND b.rn <= 3
    WHERE p.category_id IN (1, 2, 3)
");

这个查询会直接返回扁平化的结果集,每条记录对应一个场所的一个分支,且每个场所最多3条记录。

原查询问题说明

你原来的查询没有对分支数量做限制,且LEFT JOIN branches会把每个场所的所有分支都关联出来,因此会出现同一场所对应多条分支记录、分支数量超过3的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:33:33