带有条件的 Laravel 连接查询
Posted
技术标签:
【中文标题】带有条件的 Laravel 连接查询【英文标题】:Laravel join query with conditions 【发布时间】:2019-02-08 11:14:26 【问题描述】:我有 4 张桌子。
用户表:
id col1 col2
CoursesAssigned 表:
id user_id course_id approved
课程信息表:
id parent_id
CourseParents 表:
id start_date end_date
我认为表名及其列名是不言自明的。
我有 2 种用户 - i) 已分配 ii) 未分配。我将它们显示在 2 个不同的页面中。
在显示分配的学生时,我需要 users 表中的学生,他们每个人在 CoursesAssigned 表中有至少一行user_id
是他自己的用户 ID,approved
字段为 1,该行中的 course_id
有自己的 parent_id
(来自 CourseInfo)和 end_date
(来自 CourseParents) 大于或等于今天。
为了显示未分配的学生,我需要 users 表中的那些学生,他们每个人 -
要么
CoursesAssigned 表中有 NO 行,其中 user_id
是他自己的用户 ID,approved
列的值为 1。这是未分配的用户,可能存在一行有他自己的用户ID,但approved
字段包含0。
或
CoursesAssigned 表中可能存在user_id
是他自己的用户ID 和approved
字段值为1 但parent_id
来自CourseInfo 的行strong> 有来自 CourseParents 的 end_date
,该日期小于今天的日期。
我可以为分配的学生编写查询,例如:
$date=date('Y-m-d');
$records = User::join('CoursesAssigned','users.id','=','CoursesAssigned.user_id')
->join('CourseInfo','CourseInfo.id','=','CoursesAssigned.course_id')
->join('CourseParents','CourseParents.id','=',
'CourseInfo.parent_id')
->where('CoursesAssigned.approved','=',1)
->where('CourseParents.end_date','>=',$date)
->select('users.id','users.col1','users.col2')
->orderBy('users.id','desc');
但这不应该产生正确的结果,因为它不会检查 CoursesAssigned 表中的至少 1 行是否符合所有提到的标准。 Q1) 还是应该这样做?
Q2) 只获取未分配学生的查询是什么?
编辑:答案可以是 ORM、查询构建器,甚至是 Laravel 格式的原始 mysql。
EDIT2:让我在这里澄清一下场景: 我需要分别获取已分配和未分配的用户。
要获得分配的用户,我有 1 条规则:如何在 CoursesAssigned 表和父级(从 CourseInfo 表中获得至少 1 个已批准课程的用户) )该课程的 end_date(在 CourseParents 表中)大于或等于今天。
要获得未分配的学生,我有 2 条规则:
规则 1: 获取那些没有任何已批准课程的学生(即所有课程已批准 =0)。他们是未分配的学生
规则 2: 让那些获得批准的课程但没有获得批准的课程符合分配学生标准的学生。这意味着那里没有已批准的课程,其父级的 end_date 大于或等于今天。他们也是未分配的学生。
【问题讨论】:
你应该查看 laravel 关于 eloquent 和关系的文档。这一切都可以轻松地以精确的方式实现。 我详细说明了我的努力 您应该使用 Eloquent 关系来执行查询,而不是使用查询生成器。您是否在模型中定义了关系?见laravel.com/docs/5.6/… @pseudoanime,你问的是什么关系?还有模型和对应的数据库表吗? 用户表中是否存在课程分配关系(例如)。它应该在用户模型中类似于以下内容: public function coursesAssigned() return $this->hasMany('App\CoursesAssigned'); 如果您这样做,请发布您的所有关系 【参考方案1】:我仍然不完全确定您的表关系,但根据我的猜测,我想出了以下解决方案,首先使用 Eloquent
模型创建关系:
用户模型(usres
表):
namespace App;
use App\Course;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
use Notifiable;
public function courses()
return $this->hasMany(Course::class);
课程模型(CoursesAssigned
表):
namespace App;
use App\CourseInfo;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
protected $table = 'CoursesAssigned';
public function courseInfo()
return $this->belongsTo(CourseInfo::class);
CourseInfo 模型(用于CourseInfo
表):
namespace App;
use App\CourseParent;
use Illuminate\Database\Eloquent\Model;
class CourseInfo extends Model
protected $table = 'CourseInfo';
public function courseParent()
return $this->belongsTo(CourseParent::class, 'parent_id');
CourseParent 模型(用于CourseParents
表):
namespace App;
use Illuminate\Database\Eloquent\Model;
class CourseParent extends Model
protected $table = 'CourseParents';
获取分配的用户:
$assignedUsers = User::whereHas('courses', function($query)
$query->where('approved', 1)
->with(['courses.courseInfo.courseParent' => function($query)
$query->where('end_date', >= \Carbon\Carbon::now());
]);
)->get(); // paginate(...) for paginated result.
如果我的假设是正确的,这应该可以工作。先试试这个assignedUsers
然后让我知道然后我会调查它的其他要求。还要确保您了解模型之间的 Eloquent 关系并正确实现所有内容(使用正确的命名空间)。
注意:此答案不完整,需要更多信息,因为答案是通过电话与OP
直接交谈的结果(OP 打电话给我,因为我可以联系到)所以如果需要,将加班一些更改并将继续一步一步,直到我想出一个解决方案或离开它。
【讨论】:
最后一个where
部分是$query->where('end_date', >= \Carbon\Carbon::now())
。我将此部分更改为$query->where('end_date', '>=', date('Y-m-d') )
。并且使用dd()
函数,我发现查询是select * from users where exists (select * from coursesassigned where coursesassigned.user_id = users.id and approved = 1)
。这意味着 courseInfo.courseParent
关系是 ingored。这里应该做什么?
可能您没有正确遵循说明。确保在每个模型中创建所有关系。你dd
,你有完整的查询,把get->
改为->toSql()
然后dd($assignedUsers)
。
我删除了->get()
部分,然后使用了echo " sql = ".$assignedUsers->toSql();
和dd($assignedUsers->toSql(), $assignedUsers->getBindings());
。但没有得到预期的结果
我也检查了关系,这些都是正确的。解决方案可以是 ORM、查询构建器或 Laravel 格式的原始 Mysql
查询生成器或原始 MySQL 是什么?以上是关于带有条件的 Laravel 连接查询的主要内容,如果未能解决你的问题,请参考以下文章