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

Laravel中执行groupBy语句时如何获取关联关系集合

实现方案

你可以根据业务数据量选择对应的实现方式,所有方案均基于现有表结构和Eloquent查询逻辑扩展:

方案1:全量预加载+内存归集(适合中小数据量场景,代码可读性最高)

首先在BuyerZip模型中定义和买家表的关联:

// app/Models/BuyerZip.php
public function buyer()
{
    return $this->belongsTo(Buyer::class, 'buyer_id', 'id');
}

查询逻辑调整为预加载关联后按zip_id归集即可,同时保留需要的分组统计数:

$zipResult = BuyerZip::with('buyer')
    ->get()
    ->groupBy('zip_id')
    ->map(function ($relationRecords, $zipId) {
        return [
            'zip_id' => $zipId,
            'count' => $relationRecords->count(), // 对应原逻辑的分组记录总数
            // 去重处理:避免同一个买家绑定多条zip关联记录时重复返回
            'buyers' => $relationRecords->pluck('buyer')->unique('id')->values()
        ];
    })->values();

该方案不需要编写复杂原生SQL,逻辑直观,单表数据量在10w条以内时性能足够。


方案2:分块查询合并(适合大数据量场景,内存占用更低)

如果buyer_zips表数据量较大,一次性查全表会占用过高内存,可以拆分查询步骤:

// 1. 保留原有分组统计逻辑,结果按zip_id做键方便后续赋值
$zipStats = BuyerZip::selectRaw('zip_id, count(*) as count')
    ->groupBy('zip_id')
    ->get()
    ->keyBy('zip_id');

// 2. 批量查询所有涉及zip对应的关联买家数据
$zipBuyerMap = BuyerZip::with('buyer')
    ->whereIn('zip_id', $zipStats->keys())
    ->get()
    ->groupBy('zip_id')
    ->map(fn($records) => $records->pluck('buyer')->unique('id')->values());

// 3. 把买家数据合并到统计结果中
foreach ($zipStats as $zipId => $statItem) {
    $statItem->buyers = $zipBuyerMap->get($zipId, collect());
}

最终$zipStats就是目标结果,每个条目包含zip_id、关联记录总数、对应所有买家数据。


方案3:SQL聚合函数直出(适合对查询性能要求极高的场景)

如果使用MySQL数据库,可以借助GROUP_CONCAT聚合函数在分组时直接拿到关联的买家id,减少查询次数:

// 分组时同时聚合去重后的buyer_id
$zipStats = BuyerZip::selectRaw('zip_id, count(*) as count, GROUP_CONCAT(DISTINCT buyer_id) as raw_buyer_ids')
    ->groupBy('zip_id')
    ->get();

// 批量查询所有关联的买家实体
$allBuyers = Buyer::whereIn(
    'id',
    $zipStats->pluck('raw_buyer_ids')->flatMap(fn($idStr) => explode(',', $idStr))
)->get()->keyBy('id');

// 挂载买家数据,清理临时字段
$zipStats->transform(function ($item) use ($allBuyers) {
    $buyerIdList = explode(',', $item->raw_buyer_ids);
    $item->buyers = $allBuyers->only($buyerIdList)->values();
    unset($item->raw_buyer_ids);
    return $item;
});

注意:MySQL默认GROUP_CONCAT最大长度为1024字节,如果单个zip下关联的买家数量较多,会出现id被截断的问题,需要提前调大group_concat_max_len数据库配置,生产环境优先选择前两种方案稳定性更高。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:34:12