Laravel 4 查询生成器:LEFT JOIN ... AND ... 查询

Posted

技术标签:

【中文标题】Laravel 4 查询生成器:LEFT JOIN ... AND ... 查询【英文标题】:Laravel 4 Query Builder: LEFT JOIN ... AND ... query 【发布时间】:2013-06-28 14:09:57 【问题描述】:

我正在尝试从一个表中选择所有结果,并在用户 ID 匹配时与另一个表合并。

我有三个表:runs、users 和一个 run_user 数据透视表。我想从数据透视表中的“运行”和其他列(“完成”、“粘性”、“最后测试”和“难度”)中选择所有结果,但只从 run_user 中为当前用户提取数据。

在原始 SQL 中,我设法通过带有 AND 语句的 LEFT JOIN 来做到这一点:

SELECT
runs.startpoint,
runs.startpostcode,
runs.endpoint,
runs.endpostcode,
run_user.completed,
run_user.sticky,
run_user.last_tested,
run_user.difficulty
FROM runs
LEFT JOIN run_user ON run_user.run_id=runs.id AND run_user.user_id = '2'

对如何通过查询生成器执行此操作有任何建议吗?我可以在 Laravel 4 中执行 LEFT JOIN,但不知道如何将它与 AND 语句结合起来。

感谢任何帮助。

谢谢!

【问题讨论】:

【参考方案1】:

根据您的要求,这就是您使用查询生成器进行查询的方式:

DB::table('runs')
        ->leftJoin('run_user', function($join)
        
            $join->on('run_user.run_id', '=', 'runs.id')
            ->on('run_user.user_id', '=', '2');
        )
        ->get();

但是那个 JOIN 语句看起来有点奇怪,你可能想把它变成一个普通的 WHERE(除非你有非常具体的原因直接在 JOIN 子句中过滤)。

DB::table('runs')->join('run_user', 'run_user.run_id', '=', 'runs.id')->where('run_user.user_id', '=', '2')->get();

文档:http://laravel.com/docs/queries#joins

【讨论】:

谢谢,“andOn”条件似乎不适用于版本 4 (laravel.com/api/class-Illuminate.Database.Query.JoinClause.html) 你是对的,对不起。我编辑了我的答案,您可以使用 ->on()->on() 对 JOIN 进行 AND。 创建一个连接一个字段,然后一个 where 与连接上的 2 个条件不同。 如果您想在适当的位置传递动态值'run_user.user_id', '=', '2',则会出错。例如,如果我尝试 'run_user.user_id', '=', $id 它会给出未定义的变量 $id。 那是因为 $id 超出了闭包的范围。将 function($join) 更改为 function($join) use($id) 以将 $id 变量注入到闭包中,然后像你想要的那样使用它 run_user.user_id', '=', $id【参考方案2】:

如果有人想知道我在其中一个 leftJoin 参数上使用 DB::raw 来完成这项工作:

DB::table('runs')
    ->leftjoin('run_user', 'runs.id','=', 
      DB::raw('run_user.run_id AND run_user.user_id = ' . $user->id))
    ->get();

它不像我希望的那样“雄辩”,但是如果没有有效的“andOn”条件,这似乎是您想在 LEFT JOIN 中添加 AND 的唯一方法。

如果有人能提出更简洁的方法,我很想知道!

谢谢

【讨论】:

您可以使用 ->leftJoin() 和使用 ->on()->on() 的闭包来做到这一点,就像我在我的回答中展示的那样,这更干净。你的双 JOIN 子句也应该是 WHERE。 我觉得这个方案比较好。【参考方案3】:

使用这个

DB::table('runs')->select('runs.startpoint','runs.startpostcode','runs.endpoint','runs.endpostcode','run_user.completed','run_user.sticky','run_user.last_tested','run_user.difficulty')
    ->leftJoin('run_user', function($join)
    
        $join->on('run_user.run_id', '=', 'runs.id')
        ->where('run_user.user_id', '2');
    )
    ->get();

【讨论】:

【参考方案4】:

在 Laravel 4 中,您可以使用 Eloquent 查询来做到这一点。我假设您了解 Eloquent 关系并知道如何创建模型。 对于您的查询,它应该是

RunUser::where('user_id',$id)->leftjoin('runs','runs.id','=','run_user.run_id')->first();

注意 RunUser 是 run_user 表的模型。

【讨论】:

感谢您的建议。不幸的是,我在使用“where”子句时遇到了同样的问题。这适用于 run_user 表有运行记录但没有获得所有运行记录的行。 尝试改成Runs::where('id',$id)->leftjoin('run_user','run_user.run_id','=','runs.id')->first();【参考方案5】:

Provident 和用户表加入并获取所有详细信息的 ID。

   $return = DB::table(config::get('databaseconstants.TBL_USER'))
            ->leftjoin('inex_pf_details', 'inex_users.id', '=', 'inex_pf_details.pf_user_id')
            ->select('inex_pf_details.*','inex_users.*')
            ->where('inex_pf_details.id', $id)
            ->first();
    return $return;

【讨论】:

【参考方案6】:

这是必须的:

DB::table('runs')
        ->leftJoin('run_user', function($join) use ($user_id)
        
            $join->on('run_user.run_id', '=', 'runs.id')
            ->where('run_user.user_id', '=', $user_id);
        )
        ->get();

【讨论】:

您能解释一下这是如何工作的或应该做什么吗?

以上是关于Laravel 4 查询生成器:LEFT JOIN ... AND ... 查询的主要内容,如果未能解决你的问题,请参考以下文章

在 Laravel 4 查询生成器中使用 Join 删除

Laravel Eloquent LEFT JOIN WHERE NULL

laravel 简单查询生成器(join 和 where 案例)

带有 Join 和 If 条件的 Laravel 查询生成器

SQL Server LEFT OUTER JOIN 查询性能

Laravel 连接查询 AS