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 Eloquent LEFT JOIN WHERE NULL
laravel 简单查询生成器(join 和 where 案例)
带有 Join 和 If 条件的 Laravel 查询生成器