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

如何通过SQL查询实现品牌与车型的一对多关联数据查询?

问题解答

分步思路的合理性

你的分步思路并非最优方案,虽然能实现需求,但会触发N+1查询问题(1次品牌查询 + N次车型查询),数据量越大性能损耗越明显,不推荐使用。

单条SQL实现方案

完全可以通过单条SQL完成需求,利用LEFT JOIN关联两张表,再借助JSON聚合函数把车型数据聚合到对应品牌下:

原生SQL示例

SELECT 
    b.id AS brand_id,
    b.name AS brand_name,
    b.img AS brand_img,
    JSON_ARRAYAGG(
        JSON_OBJECT(
            'id', m.id,
            'name', m.name,
            'img', m.img
        )
    ) AS models
FROM brands b
LEFT JOIN models m ON b.id = m.brand_1  -- 匹配models表的brand_1外键
GROUP BY b.id, b.name, b.img;

这条SQL会将每个品牌的关联车型以JSON数组形式聚合在models字段中,一次查询即可获取所有品牌及其对应车型数据。

Laravel框架中的高效实现

Laravel无需手动编写复杂SQL,通过模型关联就能优雅解决问题,同时避免N+1查询:

  1. 定义模型关联
    在Brand模型中声明与Model的一对多关联:
// app/Models/Brand.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Brand extends Model
{
    protected $table = 'brands';
    protected $fillable = ['id', 'name', 'img'];

    public function models(): HasMany
    {
        // 关联models表的brand_1外键与brands表的id主键
        return $this->hasMany(Model::class, 'brand_1', 'id');
    }
}
  1. 预加载关联数据
    使用with()方法预加载车型,底层会自动执行两条高效SQL(一次查品牌、一次批量查所有关联车型),性能远优于手动分步查询:
$brands = Brand::with('models')->get(['id', 'name', 'img']);

如果坚持要用单条SQL实现,也可以通过查询构造器结合原生聚合函数:

$brands = DB::table('brands as b')
    ->leftJoin('models as m', 'b.id', '=', 'm.brand_1')
    ->select([
        'b.id as brand_id',
        'b.name as brand_name',
        'b.img as brand_img',
        DB::raw('JSON_ARRAYAGG(JSON_OBJECT("id", m.id, "name", m.name, "img", m.img)) as models')
    ])
    ->groupBy('b.id', 'b.name', 'b.img')
    ->get();

总结

  • 不需要手动分两步遍历查询,该方式性能劣势明显
  • 单条SQL可通过LEFT JOIN + JSON聚合实现需求
  • Laravel中优先推荐模型关联+预加载的方式,兼顾简洁性与性能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:20:27