whereHas 有缺陷,会把主表全都遍历一遍

如何在使用eloquent查询的前提下,还能实现join的效果(目的是join后用关联表的字段作为条件查询)?
而不是whereHas最终转化出来的where exists 效果,真是效率太低了。


explain select count(*) from `user` where exists (select * from `recommendation` where `user`.`id` = `recommendation`.`user_id` and `from_id` = '1');

explain select count(*) from user u join recommendation r on u.id = r.user_id where r.from_id = 1;

举例如上,第一条sql是whereHas生成的,会把主表user表完全扫一遍,一个很简单的任务,执行了几十秒,php都超时了。
而下面一条join,自己写的,一样的效果,瞬间就能跑完。

无奈的是,该路由下的功能已经全部用eloquent做的数据查询了,现在想改Query Builder也来不及了。除非下定决心重构。
请问怎么才能在eloquent中使用join查询?
跪谢!

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

不知道这个可不可以帮你

给 Eloquent 的 whereHas 加个 where in 的优化

4年前 评论
kiyoma (楼主) 4年前
讨论数量: 10

@Wi1dcard 我一开始没说清楚,我的锅(不过如果你看到标题里的whereHas应该也能想到)。我的目的是用关联表的字段作为条件查询。关联模型并做不到这一点,在模型里声明了各种relation之后,只是方便你快捷地进行select,而不能根据关联表的字段来where。整个关联模型的那篇文档只提到了whereHas这么一个东西,最终的效果就是题干中说的where exists,要多蠢有多蠢。

5年前 评论

@kiyoma 其实可以换个思路,先拿到一批 recommendation,随后拿到 recommendation 对应的 users

5年前 评论

我也发现在这个问题了,只能内关联去查

4年前 评论

请问你解决了吗?whereHas太耗时间。

4年前 评论
kiyoma (楼主) 4年前
还不出来 3年前

怎么办,有高人能解决这个问题吗?很常见吧?如何才能避免使用whereHas()?可不使用whereHas的话,又不想使用join,因为join+select查询出来的就不是eloquent了,而是collection了。

4年前 评论
还不出来 3年前

不知道这个可不可以帮你

给 Eloquent 的 whereHas 加个 where in 的优化

4年前 评论
kiyoma (楼主) 4年前

join和ORM是可以一起使用的
如:

// 分页
$query->join('a', 'a.id', 'b.id')->with('xxx')->where('xx', '')->paginate(20);

// 获取全部数据
$query->join('a', 'a.id', 'b.id')->with('xxx')->where('xx', '')->get();
4年前 评论

@zulien

file
为什么我这个 ,查询 whereHan('cash') 过滤的时候, 会把别的日期的都查询出来? 这是为什么?

cash 表有 user_id 和 divide_id 两个字段 ,一对多关联的时候用的是:下面这个,按理来说是没有问题的啊。
public function cash(){
return $this->hasMany(Cash::class , 'divide_id' , 'id');
}

4年前 评论
zulien 4年前
jxdr (作者) 4年前
jxdr (作者) 4年前
jxdr (作者) 4年前

@zulien

file

我用另一个 项目测试 , 这样查询是可以得到正确的数据 , 不知道为什么 ,

4年前 评论
zulien 4年前
zulien 4年前
jxdr (作者) 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!