
本文讲解如何在 Laravel 中通过 Eloquent 实现类似 SELECT COUNT(*) FROM users WHERE 7 = (SELECT COUNT(...) FROM lecciones_users) 的纯 SQL 逻辑,避免链式构造错误,并提供安全、可读、可维护的替代方案。
本文讲解如何在 laravel eloquent 中正确实现含关联子查询的聚合统计(如“完成全部7门课程的用户数”),指出常见链式构造误区,演示 `whereraw()` + `count()` 的精准写法,并推荐基于模型关系的更健壮替代方案。
在 Laravel 中,Eloquent 并非不支持原生 SQL 逻辑,而是要求开发者明确区分「查询构建」与「SQL 意图」。你最初的尝试存在两个关键问题:
- select() 中混入 WHERE 条件:DB::raw('where ...') 被错误地当作字段别名处理,实际会生成非法 SQL(如 SELECT COUNT(*) AS ..., where ...);
- 表别名与连接逻辑错位:原始 SQL 以 users 为主表,而你的 Eloquent 查询以 LeccionesUsers 为模型起点,却未正确反向关联 users 表,导致子查询中 users.uuid 无法解析。
✅ 正确做法是:用 whereRaw() 封装子查询条件,再调用 count() 触发聚合。假设 LeccionesUsers 模型对应 lecciones_users 表,且 users 表通过 uuid 关联,则等效代码如下:
use Illuminate\Support\Facades\DB;
$total_see_all_video = LeccionesUsers::whereRaw(
'7 = (SELECT COUNT(*) FROM users WHERE users.uuid = lecciones_users.uuid)'
)->count();
⚠️ 注意:此处子查询中的 lecciones_users.uuid 是当前模型主表的字段,无需额外 join —— 因为 whereRaw 是附加在主查询 WHERE 子句上的条件,Eloquent 会自动将 lecciones_users 作为主表引用。
若需验证生成的 SQL 是否符合预期,可在开发环境添加调试语句:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
// 查看实际执行的 SQL(不执行)
dd(LeccionesUsers::whereRaw('7 = (SELECT COUNT(*) FROM users WHERE users.uuid = lecciones_users.uuid)')->toSql());
// 或查看带绑定参数的完整语句
dd(LeccionesUsers::whereRaw('7 = (SELECT COUNT(*) FROM users WHERE users.uuid = lecciones_users.uuid)')->toRawSql());
? 更推荐的工程化方案:定义模型关系,提升可读性与可测试性。例如,在 User 模型中定义已完成课程数的访问器:
// app/Models/User.php
class User extends Model
{
protected $appends = ['completed_lessons_count'];
public function leccionesUsers()
{
return $this->hasMany(LeccionesUsers::class, 'uuid', 'uuid');
}
public function getCompletedLessonsCountAttribute()
{
return $this->leccionesUsers()->count();
}
}
然后通过集合筛选或数据库查询优化实现业务逻辑:
// 方案一:数据库层过滤(推荐,高效)
$completedUsersCount = User::whereHas('leccionesUsers', null, '>=', 7)->count();
// 方案二:应用层校验(适合复杂逻辑或小数据集)
$allUsers = User::withCount('leccionesUsers')->get();
$fullyCompleted = $allUsers->filter(fn($u) => $u->lecciones_users_count === 7)->count();
总结:Eloquent 支持原生 SQL 片段(如 whereRaw),但应严格遵循其 DSL 语义——条件归 where 系列方法,字段归 select,聚合归 count()/sum() 等。盲目拼接 DB::raw() 易导致语法错误;而善用模型关系与作用域(Scopes),才能写出既高效又易于协作维护的 Laravel 代码。










