Laravel 5.6中MySQL查询转Query Builder及DB::Raw报错求助
如何将指定MySQL查询转换为Laravel 5.6 Query Builder格式
问题背景
我需要把这条MySQL查询转换成Laravel 5.6的Query Builder格式:
SELECT paper_id,user_id,COUNT(payments.user_id),users.district FROM payments LEFT JOIN users ON payments.user_id = users.id WHERE payments.paper_id=3 GROUP BY users.district HAVING COUNT(payments.user_id)>=0;
我先后尝试了两种写法,但都遇到了问题:
第一种尝试:使用DB::Raw
$data=DB::Raw('SELECT paper_id,user_id,COUNT(payments.user_id),users.district FROM payments LEFT JOIN users ON payments.user_id = users.id WHERE payments.paper_id='.$paper_id.' GROUP BY users.district HAVING COUNT(payments.user_id)>=0 ');
问题:返回空响应 [{}]
第二种尝试:Query Builder写法
$data2=DB::table('payments') ->leftJoin('users','payments.user_id','users.id') ->select('paper_id','user_id','users.district', DB::Raw('COUNT(payments.user_id)')) ->where('payments.paper_id',$paper_id) ->groupBy('users.district') ->select(DB::Raw('HAVING COUNT(payments.user_id)>=0')) ->get();
问题:出现SQL语法错误:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error
in your SQL syntax; check the manual that corresponds to your MariaDB server
version for the right syntax to use near 'HAVING COUNT(payments.user_id)>=0 from
payments left join users on payments at line 1 (SQL: select HAVING
COUNT(payments.user_id)>=0 from payments left join users on
payments.user_id = users.id where payments.paper_id = 1 group by
users.district)
错误原因分析
- 第一种写法的问题:
DB::Raw()只是创建了一个原始SQL表达式对象,但并没有执行查询操作,所以自然返回空结果。你需要用DB::select()来包裹这个表达式才能执行查询。 - 第二种写法的问题:你错误地把
HAVING条件放到了select()方法里,Laravel Query Builder提供了专门的havingRaw()方法来处理这种原始的HAVING条件,这样写会直接导致SQL语法错误。
正确的Query Builder写法
下面是符合要求的正确写法,同时优化了字段命名和安全性:
$data = DB::table('payments') ->leftJoin('users', 'payments.user_id', '=', 'users.id') ->select( 'payments.paper_id', 'payments.user_id', // 注意:按district分组后,这个字段的值可能不唯一,建议根据实际需求调整(比如用MAX/聚合函数) 'users.district', DB::raw('COUNT(payments.user_id) as user_count') // 给统计字段起别名,方便后续使用 ) ->where('payments.paper_id', $paper_id) ->groupBy('users.district') ->havingRaw('COUNT(payments.user_id) >= 0') ->get();
额外补充
- 如果想修复第一种
DB::Raw的写法,应该用参数绑定(避免SQL注入)并配合DB::select():
$data = DB::select(DB::raw('SELECT paper_id,user_id,COUNT(payments.user_id),users.district FROM payments LEFT JOIN users ON payments.user_id = users.id WHERE payments.paper_id=? GROUP BY users.district HAVING COUNT(payments.user_id)>=0'), [$paper_id]);
- 另外,
HAVING COUNT(payments.user_id)>=0这个条件其实可以省略,因为COUNT函数的结果永远是非负的,不会过滤掉任何分组结果。
内容的提问来源于stack exchange,提问作者Naveed Sheriffdeen
相关产品推荐
相关产品推荐

