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

如何使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:18:28