如何在Laravel控制器中编写给定的MySQL查询语句
Laravel 控制器中用户匹配查询的实现写法
你可以直接通过Laravel查询构造器实现对应原生MySQL的查询逻辑,以下是可直接复用的代码:
- 与原SQL逻辑完全一致的查询构造器写法
<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\DB; class UserMatchController extends Controller { public function getMatchList() { $matchList = DB::table('users as u') ->join('user_matches', function ($join) { // 拼接JOIN的两个关联条件 $join->on('u.id', '=', 'user_matches.user_id') ->whereRaw( 'FIND_IN_SET(user_matches.to_user_id, ?)', [ // 对应原SQL中的GROUP_CONCAT子查询 DB::table('users')->selectRaw('GROUP_CONCAT(id)')->value('GROUP_CONCAT(id)') ] ); }) ->select('user_matches.*') ->get(); return $matchList; } }
- 小数据量场景下更简洁的优化写法
原SQL中FIND_IN_SET匹配的是全量用户id集合,小数据量下可以提前取出id集合拼接后传入,减少SQL子查询嵌套:
public function getMatchList() { // 提前查询所有用户id,拼接为逗号分隔字符串 $allUserIds = DB::table('users')->pluck('id')->implode(','); $matchList = DB::table('users as u') ->join('user_matches', function ($join) use ($allUserIds) { $join->on('u.id', '=', 'user_matches.user_id') ->whereRaw('FIND_IN_SET(user_matches.to_user_id, ?)', [$allUserIds]); }) ->select('user_matches.*') ->get(); return $matchList; }
- 大数据量场景下的高性能等价写法
FIND_IN_SET函数无法用到索引,当用户表数据量超过10万级时查询性能会很差,可以用whereExists改写实现完全一致的业务逻辑,查询效率可提升数倍:
public function getMatchList() { $matchList = DB::table('users as u') ->join('user_matches', function ($join) { $join->on('u.id', '=', 'user_matches.user_id') ->whereExists(function ($query) { $query->select(DB::raw(1)) ->from('users') ->whereColumn('users.id', 'user_matches.to_user_id'); }); }) ->select('user_matches.*') ->get(); return $matchList; }
注意:如果你已经定义了
User和UserMatch的Eloquent模型,也可以把上述代码中的DB::table()调用替换为对应模型调用,写法逻辑完全一致。
内容的提问来源于stack exchange,提问作者Kirtan
相关产品推荐
相关产品推荐

