Laravel Eloquent技术问询:获取拥有至少一条广告的用户
嘿,我来帮你搞定这个查询的问题~ 先从你的原SQL说起,再给你对应的Eloquent实现,顺便优化一下写法:
原SQL的优化点
你的原SQL确实能实现需求,但存在冗余逻辑:你已经用了INNER JOIN anuncio,这一步会自动过滤掉没有关联广告的用户(因为内连接只保留两边都有匹配数据的行),后面的WHERE (SELECT COUNT(*) ...) > 0完全是重复过滤,没必要保留。
优化后的精简SQL如下:
SELECT users.id, COUNT(anuncio.id) AS total FROM users INNER JOIN anuncio ON users.id = anuncio.usuario_id GROUP BY users.id
这个版本和原SQL结果完全一致,但执行效率更高。
基于User模型的Eloquent实现
假设你已经在User模型里定义了和Anuncio的一对多关联(注意模型名要符合Laravel的命名规范,一般是单数首字母大写):
// app/Models/User.php public function anuncios() { return $this->hasMany(Anuncio::class, 'usuario_id'); }
下面给你几种常用的Eloquent写法,按需选择:
写法1:最简洁的推荐写法(has() + withCount())
has('anuncios')会自动筛选出至少拥有一条广告的用户,withCount()用来统计每个用户的广告数量,代码可读性拉满:
$users = User::has('anuncios') ->withCount('anuncios as total') ->select('id') ->get();
Eloquent会自动帮你生成和优化后SQL一致的高效查询语句。
写法2:完全映射优化后SQL的写法(join() + groupBy())
如果你想完全手动对应SQL的逻辑,可以用join方式,需要引入DB门面:
use Illuminate\Support\Facades\DB; $users = User::join('anuncio', 'users.id', '=', 'anuncio.usuario_id') ->select('users.id', DB::raw('COUNT(anuncio.id) as total')) ->groupBy('users.id') ->get();
写法3:支持额外过滤广告的场景(whereHas())
如果之后需要对广告加筛选条件(比如只统计已发布的广告),可以用whereHas():
$users = User::whereHas('anuncios', function($query) { // 这里可以添加广告的过滤条件,例如: // $query->where('status', 'published'); }) ->withCount('anuncios as total') ->select('id') ->get();
补充小提示
- 如果你只需要获取有广告的用户,不需要统计数量,直接用
User::has('anuncios')->get()就够了。 - 确保
Anuncio模型里的外键usuario_id和User模型的主键id对应正确,关联关系不要写错哦~
内容的提问来源于stack exchange,提问作者Santos Osmin Urrutia
相关产品推荐
相关产品推荐

