Laravel 8联表查询时如何筛选总调研数与已完成调研数相等的项目
Laravel 8 筛选已完成调研数等于总调研数的项目实现方案
核心实现逻辑
你当前的查询已经通过两个子查询在select段计算出了每个项目的total_surveys(总调研数)和completed_surveys(已完成调研数),要筛选两个值相等的项目,有两种适配Laravel 8查询构造器的常用写法,核心是匹配SQL的执行顺序,避免出现“自定义字段不存在”的报错。
方案1:复用子查询直接做过滤条件(兼容性最高)
因为SQL执行顺序中where条件的判定早于select段的自定义字段计算,不能直接用别名做where判定,需要把两个计数的子查询原样放到where比对条件中,改动量最小:
$today = date('Y-m-d'); $projects = \DB::table('projects') ->join('companies', 'projects.company_id', '=', 'companies.id') ->select( 'projects.*', 'companies.company_name as company_name', // 替换原有字符串拼接为参数绑定,规避SQL注入风险 \DB::raw('(SELECT COUNT(*) FROM surveys WHERE DATE(surveys.end_date) < ? AND surveys.project_id = projects.id) as completed_surveys', [$today]), \DB::raw('(SELECT COUNT(*) FROM surveys WHERE surveys.project_id = projects.id) as total_surveys') ) ->where(function ($query) use ($today) { $query->where( \DB::raw('(SELECT COUNT(*) FROM surveys WHERE DATE(surveys.end_date) < ? AND surveys.project_id = projects.id)', [$today]), '=', \DB::raw('(SELECT COUNT(*) FROM surveys WHERE surveys.project_id = projects.id)') ); }) ->paginate(6);
方案2:用having从句做别名过滤(写法最简洁)
having从句的执行时机在select段的自定义字段计算完成之后,因此可以直接使用select中定义的两个别名做比对,不需要重复写两遍子查询,代码可维护性更强:
$today = date('Y-m-d'); $projects = \DB::table('projects') ->join('companies', 'projects.company_id', '=', 'companies.id') ->select( 'projects.*', 'companies.company_name as company_name', \DB::raw('(SELECT COUNT(*) FROM surveys WHERE DATE(surveys.end_date) < ? AND surveys.project_id = projects.id) as completed_surveys', [$today]), \DB::raw('(SELECT COUNT(*) FROM surveys WHERE surveys.project_id = projects.id) as total_surveys') ) // 直接引用select中定义的两个别名做相等比对 ->having('completed_surveys', '=', \DB::raw('total_surveys')) ->paginate(6);
注意事项
- 不要用普通的
where从句直接引用completed_surveys、total_surveys这两个自定义别名,否则数据库会因为找不到对应字段抛出语法错误。 - 原有代码中直接把
date('Y-m-d')拼接到raw语句里的写法建议替换为参数绑定,哪怕当前传入的是固定生成的时间值,也符合Laravel的安全编码规范,避免后续维护过程中引入SQL注入风险。 - 如果surveys表数据量较大,建议给
project_id、end_date两个字段建立联合索引,降低两个count子查询的扫描开销,提升查询速度。
内容的提问来源于stack exchange,提问作者Rajen Trivedi
相关产品推荐
相关产品推荐

