如何使用Laravel Eloquent实现入站数大于出站数的用户记录查询
Laravel Eloquent 实现入站通行记录数大于出站记录数的用户查询
以下几种实现都不需要手动拼接长段原生SQL,完全使用框架原生能力,代码可维护性更高,你可以根据场景选择:
方案1:withCount 实现(最符合Eloquent使用规范,优先选)
先在User模型中定义和通行记录的一对多关联:
// app/Models/User.php public function passages() { return $this->hasMany(Passage::class); }
查询代码:
$users = User::withCount([ 'passages as in_count' => fn($q) => $q->where('direction', 'in'), 'passages as out_count' => fn($q) => $q->where('direction', 'out') ]) ->havingRaw('in_count > out_count') ->get();
- 写法最简洁,不需要手动写Join逻辑,框架自动处理关联查询
- 返回的User模型自带
in_count、out_count属性,后续展示数值可直接调用 - 避免硬编码SQL片段,减少语法错误和SQL注入风险
方案2:匹配原有子查询逻辑的实现
如果你需要完全对齐你最初手写的SQL逻辑,可以用查询构造器生成子查询对象,不用手动拼接SQL字符串:
$inCount = Passage::selectRaw('count(*)') ->whereColumn('user_id', 'users.id') ->where('direction', 'in'); $outCount = Passage::selectRaw('count(*)') ->whereColumn('user_id', 'users.id') ->where('direction', 'out'); $users = User::leftJoin('passages', 'passages.user_id', 'users.id') ->where($inCount, '>', $outCount) ->groupBy('users.id') ->get();
框架会自动将传入的查询构造器对象解析为对应的子查询SQL,和你最初手写的SQL执行逻辑完全一致。
方案3:大数据量场景的高性能实现
如果passages表数据量较大,推荐用单次Join+条件聚合的写法,只做一次表关联即可完成两类记录计数,性能比多子查询方案更高:
$users = User::select('users.*') ->leftJoin('passages', 'users.id', '=', 'passages.user_id') ->selectRaw('count(case when passages.direction = ? then 1 end) as in_count', ['in']) ->selectRaw('count(case when passages.direction = ? then 1 end) as out_count', ['out']) ->groupBy('users.id') ->havingRaw('in_count > out_count') ->get();
内容的提问来源于stack exchange,提问作者Nikolay Chervon
相关产品推荐
相关产品推荐

