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

如何在Laravel中查询addSelect创建的字段?

问题:Laravel中无法查询addSelect创建的字段

我用Laravel编写了如下查询语句,通过addSelect新增了submission_date、resubmission_date、error_date三个字段,这些字段能正常在数据表格显示,但当我尝试通过submission_date做范围查询时,报错:

1054 Unknown Column submission_date.

原始查询代码:

DB::connection('mysql_slave')
    ->table('applications')
    ->whereNull('applications.deleted_at')
    ->when($column != 'contract_return_date' && $column != 'contract_delivery_date',function ($query) use ($column,$date_from,$date_to){
        return $query->whereBetween('applications.'.$column, [$date_from, $date_to]);
    })
    ->join('customers','applications.customer_id','=','customers.id')
    ->join('departments','applications.department_id','=','departments.id')
    ->select([
        'applications.id',
        'applications.customer_id',
        DB::raw('CONCAT(IFNULL(customers.last_name,"")," ",customers.first_name ) as customers_name'),
        DB::raw('CONCAT(IFNULL(applications.last_name,"")," ",applications.first_name ) as contract_name'),
        'applications.offer_type as offer_type',
        'applications.status_id',
        'applications.contract_no',
        'applications.current_provider',
        'applications.extra_offer',
        'applications.offer_warranty',
        'applications.department_id',               
        'customers.mobile_phone as customer_mobile',
        'applications.program as program',
        'applications.saled_by_text as saler',
        'departments.name as department',
        'applications.created_at as created_at',
        'applications.created_at as saled_at',
        DB::raw('IF(applications.sale=1,"NAI","OXI") as sale'),
    ])

    ->addSelect(['submission_date'=> StatusLog::select('created_at')
        ->whereColumn('application_id','applications.id')
        ->where('status','=',1)
        ->latest()
        ->take(1)
    ])

    ->addSelect(['resubmission_date'=> StatusLog::select('created_at')
        ->whereColumn('application_id','applications.id')
        ->where('status','=',2)
        ->latest()
        ->take(1)
    ])
    ->addSelect(['error_date' => StatusLog::select('created_at')
        ->whereColumn('application_id','applications.id')
        ->whereIn('status', [5, 6])
        ->latest()
        ->take(1)
    ]) ->when($column == 'contract_delivery_date',function ($query) use ($date_from,$date_to){
        return $query->whereBetween('submission_date', [$date_from, $date_to]);
    });

解决方案

出现这个错误的核心原因是:MySQL的执行顺序中,WHERE子句的执行早于SELECT子句,因此无法直接在WHERE里引用SELECT(包括addSelect)中定义的字段别名。以下是两种可行的解决方法:

方法1:直接在WHERE条件中复用子查询逻辑

把submission_date对应的子查询直接写到whereBetween的第一个参数里,替换原来的字段别名:

->when($column == 'contract_delivery_date', function ($query) use ($date_from, $date_to) {
    return $query->whereBetween(
        // 复用submission_date的子查询逻辑
        StatusLog::select('created_at')
            ->whereColumn('application_id', 'applications.id')
            ->where('status', '=', 1)
            ->latest()
            ->take(1),
        [$date_from, $date_to]
    );
});

这种写法简单直接,适合只在单个地方使用该字段查询的场景,但如果多个地方需要用到这个逻辑,会出现代码重复。

方法2:使用子查询/CTE先构建完整数据集,再在外层查询

先通过子查询生成包含所有字段(包括submission_date)的临时数据集,再在外层查询中对这个临时数据集的字段做条件筛选:

// 第一步:构建包含所有字段的子查询
$subQuery = DB::connection('mysql_slave')
    ->table('applications')
    ->whereNull('applications.deleted_at')
    ->when($column != 'contract_return_date' && $column != 'contract_delivery_date', function ($query) use ($column,$date_from,$date_to){
        return $query->whereBetween('applications.'.$column, [$date_from, $date_to]);
    })
    ->join('customers','applications.customer_id','=','customers.id')
    ->join('departments','applications.department_id','=','departments.id')
    ->select([
        'applications.id',
        'applications.customer_id',
        DB::raw('CONCAT(IFNULL(customers.last_name,"")," ",customers.first_name ) as customers_name'),
        DB::raw('CONCAT(IFNULL(applications.last_name,"")," ",applications.first_name ) as contract_name'),
        'applications.offer_type as offer_type',
        'applications.status_id',
        'applications.contract_no',
        'applications.current_provider',
        'applications.extra_offer',
        'applications.offer_warranty',
        'applications.department_id',               
        'customers.mobile_phone as customer_mobile',
        'applications.program as program',
        'applications.saled_by_text as saler',
        'departments.name as department',
        'applications.created_at as created_at',
        'applications.created_at as saled_at',
        DB::raw('IF(applications.sale=1,"NAI","OXI") as sale'),
    ])
    ->addSelect(['submission_date'=> StatusLog::select('created_at')
        ->whereColumn('application_id','applications.id')
        ->where('status','=',1)
        ->latest()
        ->take(1)
    ])
    ->addSelect(['resubmission_date'=> StatusLog::select('created_at')
        ->whereColumn('application_id','applications.id')
        ->where('status','=',2)
        ->latest()
        ->take(1)
    ])
    ->addSelect(['error_date' => StatusLog::select('created_at')
        ->whereColumn('application_id','applications.id')
        ->whereIn('status', [5, 6])
        ->latest()
        ->take(1)
    ]);

// 第二步:基于子查询做外层查询,处理contract_delivery_date的条件
$query = DB::table($subQuery, 'sub')
    ->when($column == 'contract_delivery_date', function ($q) use ($date_from, $date_to) {
        return $q->whereBetween('sub.submission_date', [$date_from, $date_to]);
    });

// 获取最终结果
$results = $query->get();

这种方法逻辑更清晰,避免了代码重复,适合复杂查询场景,后续如果要对其他新增字段做查询,也可以直接在外层处理。


内容的提问来源于stack exchange,提问作者Vasilis13

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:40:56