You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 12:24:03