Laravel关联查询如何平均值_Laravel平均值关联查询字段【方法】

轻瑶大大_9371

轻瑶大大_9371

2026-04-26

542人浏览

原创

withavg() 是最轻量方式查询关联表字段平均值,仅添加如 posts_avg_views 的数字属性,不加载关联数据;支持自定义字段名但仅限一级关联,多聚合或过滤需用 selectraw()+join 或子查询。

laravel关联查询如何平均值_laravel平均值关联查询字段【方法】

用 withAvg() 直接查关联表平均值

想在查主模型时顺带拿到关联表某个字段的平均值,withAvg() 是最轻量、最符合直觉的方式。它不会加载关联记录本身,只执行一个子查询或 JOIN + AVG 聚合,性能比 with() + 手动计算好得多。

常见错误是把它当 with() 用,以为会返回关联模型数据——其实它只往主模型实例上挂一个形如 avg_rating 的属性(名称可自定义),且该属性是数字或 null。

  • User::withAvg('posts', 'views')->get() 会给每个 User 实例加一个 posts_avg_views 属性(默认命名规则)
  • 想自定义字段名,用数组语法:withAvg(['posts' => 'avg_views'], 'views')
  • 注意:关联关系必须已定义,且数据库字段存在;如果某用户没有 posts,avg_views 为 null,不是 0
  • 不支持多层嵌套关联(比如 user.posts.comments),只能一级关联

需要同时查多个聚合值?用 selectRaw() + leftJoin()

当你要的不只是平均值,还想要关联表的计数、最大值、甚至主表和关联表字段混算(比如“用户发帖平均阅读量”),withAvg() 就不够用了。这时候得手动写 JOIN 和聚合,selectRaw() 是最可控的方式。

容易踩的坑是忘记 groupBy() —— 没它的话,聚合结果会错乱,MySQL 8.0+ 甚至直接报错 Expression #1 of SELECT list is not in GROUP BY clause。

laravel-specialist
laravel-specialist

精通 Laravel 10+,遵循现代 PHP 实践的 Laravel 专家。擅长优雅语法、Eloquent ORM、队列系统及企业级特性...

下载
  • 示例:查每个用户的帖子平均阅读量和总评论数
User::select('users.*')
    ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
    ->selectRaw('AVG(posts.views) as avg_views')
    ->selectRaw('COUNT(comments.id) as total_comments')
    ->leftJoin('comments', 'posts.id', '=', 'comments.post_id')
    ->groupBy('users.id')
    ->get();
  • 注意 groupBy('users.id') 必须包含所有非聚合字段;若用 select('*'),需明确列出 users 表所有字段,否则可能出错
  • LEFT JOIN 保证没发帖的用户也能查出来(avg_views 为 null),用 INNER JOIN 则只返回有数据的用户
  • has() 或 whereDoesntHave() 配合平均值筛选

    有时候你不是要展示平均值,而是要用它做条件过滤——比如“只查平均评分 ≥ 4.5 的商品”。这时候不能靠 withAvg(),因为它只是附加数据,不参与 WHERE。

    正确做法是用子查询或 JOIN 做聚合过滤,Laravel 提供了 whereHas() 的增强版:whereHasMorph() 不适用,但可以用 whereHas() 搭配闭包里的 selectRaw() + having()。

    • 推荐写法(子查询):
    Product::whereExists(function ($query) {
        $query->selectRaw(1)
              ->from('reviews')
              ->whereColumn('reviews.product_id', 'products.id')
              ->groupBy('reviews.product_id')
              ->havingRaw('AVG(reviews.rating) >= ?', [4.5]);
    })->get();
    
  • 或者用 JOIN + having()(需确保主表字段在 GROUP BY 中)
  • 别在 whereHas() 闭包里直接写 avg() —— Laravel 不会自动把它转成 HAVING,会当成 WHERE 处理,导致 SQL 错误
  • 如果平均值条件涉及多个关联表(比如“用户+订单+评价”三级平均),子查询更清晰,JOIN 容易混乱
  • 关联平均值字段在 Eloquent 访问时的陷阱

    用 withAvg() 或 selectRaw() 加的平均值字段,看起来像模型属性,但它们不是真正意义上的 Eloquent 属性——不走 $casts、不触发 getAttribute()、也不能直接用于 toArray() 之外的序列化逻辑(比如 API Resource 中未显式添加会丢失)。

    • 如果你在 Resource 里写 $this->avg_views,它能取到值;但写 $this->getOriginal('avg_views') 会返回 null,因为不是原始数据库字段
    • 想统一处理这类计算字段,建议在模型中加访问器:
    protected $appends = ['avg_rating'];
    
    public function getAvgRatingAttribute()
    {
        return $this->attributes['posts_avg_rating'] ?? 0;
    }
    
  • 注意:访问器名和 withAvg() 生成的属性名要对齐;否则取不到值
  • 如果用了 selectRaw(),字段名是你自己写的,访问器可以直接对应,不用依赖 Laravel 的默认命名逻辑
  • 关联平均值看着简单,但字段来源(withAvg / selectRaw / 子查询)、作用域(展示用 or 过滤用)、以及后续访问方式(原生属性 or 访问器 or Resource 显式赋值)这三者一旦错配,就容易查不到值、报错、或 API 返回空。尤其在分页 + 聚合混合场景下,GROUP BY 和 SELECT 字段的严格匹配最容易被忽略。

    相关文章

    PHP速学视频免费教程(入门到精通)
    PHP速学视频免费教程(入门到精通)

    PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

    下载

    相关标签:

    laravel

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

    相关专题

    更多
    laravel组件介绍
    laravel组件介绍

    laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

    2024.04.09

    857

    10

    laravel中间件介绍
    laravel中间件介绍

    laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

    2024.04.09

    835

    9

    laravel使用的设计模式有哪些
    laravel使用的设计模式有哪些

    laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

    2024.04.09

    2488

    10

    thinkphp和laravel哪个简单
    thinkphp和laravel哪个简单

    对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

    2024.04.10

    4301

    7

    laravel入门教程
    laravel入门教程

    本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

    2025.08.05

    6190

    22

    laravel实战教程
    laravel实战教程

    本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

    2025.08.05

    4096

    13

    laravel面试题
    laravel面试题

    本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

    2025.08.05

    7689

    7

    PHP高性能API设计与Laravel服务架构实践
    PHP高性能API设计与Laravel服务架构实践

    本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

    2026.03.04

    1476

    29

    Laravel 框架安装指南
    Laravel 框架安装指南

    本指南详解 Laravel 框架安装全流程,涵盖 PHP 8.1+ 环境配置、Composer 依赖管理工具安装及国内镜像源优化。重点演示使用 composer create-project 命令创建 Laravel 10/11 项目,解决常见安装错误与依赖冲突。从环境搭建到项目初始化,助您快速完成 Laravel 开发环境部署,为后续 Web 应用开发奠定基础。适合 PHP 初学者与框架迁移开发者参考。

    2026.04.09

    215

    6

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    如何安装 Composer
    如何安装 Composer

    共1课时 | 212人学习

    Composer手册
    Composer手册

    共0课时 | 0人学习