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

Laravel原生查询可嵌套子查询吗?我的查询报1055错误求排查

Laravel原生查询嵌套子查询问题解析

当然可以在Laravel的原生查询里嵌套子查询!你的思路方向是对的,但当前报错是MySQL严格模式和GROUP BY规则导致的,咱们来一步步梳理问题和解决方案:

错误原因分析

你遇到的错误 SQLSTATE[42000]: Syntax error or access violation: 1055 'tenderpo_2019.ac.bid_invitation_id' isn't in GROUP BY,本质是MySQL默认开启了ONLY_FULL_GROUP_BY严格模式。这个模式有个核心要求:SELECT语句中出现的非聚合函数列,必须全部包含在GROUP BY子句中。

你的查询里,SELECT中的子查询用到了ac.bid_invitation_id,但这个字段并没有出现在GROUP BY的method列表里。当你按method分组时,同一个method可能对应多个不同的ac.bid_invitation_id,MySQL无法确定应该用哪个值来执行子查询,所以触发了这个错误。

解决方案

方案1:将子查询改为与分组维度匹配

把原本针对单个bid_invitation_id的统计,改成针对整个method分组的统计,确保子查询和GROUP BY的维度一致:

DB::table('awarded_contracts as ac') 
->select( 
    DB::raw("COUNT(ac.id) AS numOfContracts"), 
    DB::raw("SUM(ac.contract_amount) AS sumOfContractAmounts"), 
    DB::raw("(SELECT COUNT(bs.id) 
              FROM bid_submissions bs 
              JOIN bid_invitations bi2 ON bs.bid_invitation_id = bi2.id 
              JOIN procurement_plan_entries ppe2 ON bi2.procurement_plan_entry_id = ppe2.id 
              LEFT JOIN procurement_methods pm2 ON ppe2.procurement_method_id = pm2.id 
              LEFT JOIN procurement_methods pm3 ON bi2.procurement_method_id = pm3.id 
              WHERE (CASE WHEN bi2.procurement_method_id = '0' THEN pm2.title ELSE pm3.title END) = method) AS numOfBidSubmissions"), 
    DB::raw("(CASE WHEN bi.procurement_method_id ='0' THEN pm.title ELSE pm2.title END) as method") 
) 
->join('bid_invitations as bi', 'bi.id', '=', 'ac.bid_invitation_id') 
->leftJoin('procurement_plan_entries as ppe', 'ppe.id', '=', 'bi.procurement_plan_entry_id') 
->join('procurement_methods as pm', 'ppe.procurement_method_id', '=', 'pm.id') 
->leftJoin('procurement_methods as pm2', 'pm2.id', '=', 'bi.procurement_method_id') 
->groupBy('method') 
->get();

方案2:预统计投标数后关联(更高效推荐)

先通过子查询预统计每个bid_invitation_id对应的投标数量,再将这个临时表关联到主查询中,避免在SELECT子句中嵌套子查询的问题,同时查询效率更高:

DB::table('awarded_contracts as ac')
->select(
    DB::raw("COUNT(ac.id) AS numOfContracts"),
    DB::raw("SUM(ac.contract_amount) AS sumOfContractAmounts"),
    DB::raw("SUM(COALESCE(bs_count.total, 0)) AS numOfBidSubmissions"), // 按method汇总投标数
    DB::raw("(CASE WHEN bi.procurement_method_id ='0' THEN pm.title ELSE pm2.title END) as method")
)
->join('bid_invitations as bi', 'bi.id', '=', 'ac.bid_invitation_id')
->leftJoin('procurement_plan_entries as ppe', 'ppe.id', '=', 'bi.procurement_plan_entry_id')
->join('procurement_methods as pm', 'ppe.procurement_method_id', '=', 'pm.id')
->leftJoin('procurement_methods as pm2', 'pm2.id', '=', 'bi.procurement_method_id')
// 关联预统计的投标数临时表
->leftJoin(
    DB::table('bid_submissions')
        ->select('bid_invitation_id', DB::raw('COUNT(id) as total'))
        ->groupBy('bid_invitation_id')
        ->getQuery(), // 获取原生查询构建器实例用于关联
    'bs_count.bid_invitation_id', '=', 'ac.bid_invitation_id'
)
->groupBy('method')
->get();

不推荐的临时方案:关闭ONLY_FULL_GROUP_BY

虽然可以通过修改MySQL配置或在查询前执行SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));来关闭该模式,但这会导致查询结果的不确定性(MySQL会随机选择分组内的字段值),所以不建议在生产环境使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:16:19