php - How to write eloquent left join with subquery?
问题描述
I want to write a left join query with a subquery in eloquent. I have two tables, lessons and lesson_user.
lesson
lesson_id | name | grade
lesson_user
lesson_id|user_id
If a particular student is participating a lesson, his id will be in lesson_user table.
I want to get all the lessons for a grade, and if an user participating a lesson, then with his id.
Result would be: for user_id 5 and grade 3
grade lesson user_id
3 java 5
3 C++ 5
3 Python NULL //He is not participating
Here the user id will come as an paramter, I tried this but didn't work.
public function getAll($grade_id, $user_id)
{
$lessons = Lesson::where('grade_id', $grade_id);
if($user_id != null){
$sub = LessonUser::where('user_id', $user_id);
$lessons = $lessons->leftJoin(DB::raw("($sub->toSql()) as b"), 'b.lesson_id', '=', 'lesson.id');
}
$lessons = $lessons
->select("lesson.id", "lesson.name", "user_id", "grade")
->get();
return $lessons;
}
PS: Each lesson has a grade.
Edit:
instead of sub-query and code in the if block, i used this code initially. But it gives invalid results. It returns lessons which are not belongs to grades.
$lessons = $lessons->leftJoin('lesson_user as b', 'b.lesson_id', '=', 'lesson.id');
$lessons = $lessons->where("b.user_id", $user_id)->orWhereNull("b.user_id");
Thank you :)
解决方案
我的建议是where('user_id', $user_id)
在 join 子句中使用,这会使查询更具可读性:
public function getAll($grade_id, $user_id)
{
return Lesson::query()
->leftJoin('lesson_user', function (JoinClause $join) use ($user_id) {
$join->on('lesson_user.lesson_id', '=', 'lesson.id')
->when($user_id !== null, function ($query) use ($user_id) {
$query->where('lesson_user.user_id', $user_id);
});
})
->where('lesson.grade', $grade_id)
->select([
'lesson.id',
'lesson.name',
'lesson.grade',
'lesson_user.user_id',
]);
->get();
}
推荐阅读
- python - 网状新手:如何从这个 python 脚本中获取对象以在 R 中使用?
- discord - 狙击命令不狙击消息
- webpack - Service Worker 无法使用不同的 scriptURL 进行更新
- jenkins - 詹金斯:有没有办法可以将文件作为詹金斯构建参数加载?
- vba - Microsoft word VBA 宏仅搜索某些表
- react-native - 反应原生可拖动部分列表
- r - 使用 likert 包在 R 中绘制两个或多个组
- ios - 为什么我的 Azure B2C 访问令牌没有传递到应用程序中?
- julia - 是否可以在 Julia 中将 Array{Num,1} 转换为 Array{Float64,1}?
- c++ - 使用 free() 通过 new 运算符释放堆分配的变量时会导致内存泄漏吗?