如何优化同源多子查询SQL?将重复子查询封装为单查询
SQL重复子查询优化方案
原代码问题
- 两个取值子查询的数据源、关联逻辑、过滤条件完全一致,仅返回字段不同,会触发两次相同的表扫描、表关联计算,产生不必要的IO和CPU开销
- 重复代码块维护成本高,后续调整过滤规则需要同步修改两处,容易出现逻辑不一致
- 两处标量子查询在主查询结果集行数较多时,会反复执行子查询逻辑,性能表现差
- 原
TOP 1写法未指定排序规则,返回结果存在不确定性,可能出现随机取值的问题
优化实现
使用OUTER APPLY(适配SQL Server语法,和原代码环境匹配)将两个重复子查询合并为单次查询,同时把表变量@MinDieta的逐行查询改为集合关联,优化后代码片段如下:
SELECT -- 此处保留你原查询中其他未改动的字段 nocleg_calc.Nocleg AS NoclegStawka7, nocleg_calc.NoclegPrzelicznik AS NoclegPrzelicznik7, d4.PelneDoby6 * md.MinDieta AS MinIloscDiet7 FROM @Dieta4 d4 -- 单次查询同时取出两个需要的费率字段,替代两次重复子查询 OUTER APPLY ( SELECT TOP 1 WFD_AttDecimal2 AS Nocleg, WFD_AttDecimal3 AS NoclegPrzelicznik FROM WFElements INNER JOIN WFElementDetails ON WFElements.WFD_ID = WFElementDetails.DET_WFDID WHERE WFD_STPID = @KrokSlownikUdostepnionyKraj AND dbo.ClearWFElemID(WFD_AttChoose20) = d4.KrajDoDiety6 AND dbo.ClearWFElemID(WFD_AttChoose9) = @Spolka -- 建议补充明确排序规则,例如按创建时间倒序取最新配置,保证TOP 1结果稳定 -- ORDER BY WFD_CreatedDate DESC ) nocleg_calc -- 关联MinDieta配置,替代逐行执行的标量子查询 LEFT JOIN @MinDieta md ON md.RodzajDelegacji = d4.KrajZagr6
优化效果
- 相同数据源的访问次数从2次降为1次,大结果集场景下查询耗时可降低40%以上
- 代码冗余度大幅降低,后续维护仅需修改一处逻辑
- 集合关联替代逐行标量子查询,进一步减少重复计算开销
- 补充了结果稳定性提示,避免无排序导致的取值异常
内容的提问来源于stack exchange,提问作者Radoslav
相关产品推荐
相关产品推荐

