带有条件的 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> 有来自 CourseParentsend_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 连接查询的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Eloquent 查询,带有连接、计数和分组依据

sql左连接查询+右表带有条件的实现

laravel-model实现复杂的查询语句

laravel-model实现复杂的查询语句

如何使用左连接和内连接编写 laravel 查询?

Laravel:如何编写关于 belongsToMany 关系的连接计数查询?