Laravel Eloquent 如何查询符合条件的魅力与说服力评估总经验值最高用户
实现方案
核心逻辑
不需要预加载全部evaluations关联数据,直接在数据库层完成总分计算,相比将关联数据拉取到PHP内存遍历求和,查询效率更高,也能直接按总分排序定位目标用户。
对应计算规则拆解:
- 单独统计每个用户所有
charisma = true的evaluations记录的exp求和值 - 单独统计每个用户所有
persuasion = true的evaluations记录的exp求和值 - 两个求和值相加为用户总评估分,空值统一处理为0
- 沿用原有筛选条件:匹配指定commision_id、关联角色level=2,按总评估分倒序取第一条即为目标用户
可直接复用的实现代码
原生selectRaw写法
$topUser = User::query() // 原有基础筛选条件 ->where('commision_id', $data['commision']) ->whereHas('role', function ($query) { $query->where('level', 2); }) // 关联计算总分,兼容空值异常 ->selectRaw( 'users.*, COALESCE( ( SELECT COALESCE(SUM(exp), 0) FROM evaluations WHERE evaluations.user_id = users.id AND charisma = true AND exp IS NOT NULL ) + ( SELECT COALESCE(SUM(exp), 0) FROM evaluations WHERE evaluations.user_id = users.id AND persuasion = true AND exp IS NOT NULL ), 0 ) AS total_eval_score' ) // 按总分倒序取最高 ->orderByDesc('total_eval_score') ->first();
Laravel内置关联聚合写法
如果习惯使用框架封装的withSum关联聚合语法,可使用等效写法,代码可读性更强:
$topUser = User::query() ->where('commision_id', $data['commision']) ->whereHas('role', function ($query) { $query->where('level', 2); }) // 分别计算两个维度的exp总和,自动生成关联聚合字段 ->withSum([ 'evaluations as charisma_exp_sum' => function ($query) { $query->where('charisma', true)->selectRaw('COALESCE(SUM(exp), 0)'); }, 'evaluations as persuasion_exp_sum' => function ($query) { $query->where('persuasion', true)->selectRaw('COALESCE(SUM(exp), 0)'); } ]) // 计算总分 ->selectRaw('(COALESCE(charisma_exp_sum, 0) + COALESCE(persuasion_exp_sum, 0)) AS total_eval_score') ->orderByDesc('total_eval_score') ->first();
关键注意点
- 移除了原代码中无逻辑的空
with(['evaluations' => ...])写法,避免无意义预加载全量关联数据,减少内存占用 - 所有求和逻辑都增加了
COALESCE空值处理,避免用户在某个维度没有评估记录时,查询返回null导致总分计算异常、排序错位 - 计算时增加
exp IS NOT NULL判断,适配evaluations表中exp字段可空的结构设计 - 两种写法的SQL执行效率基本一致,可根据自身代码习惯选择
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

