【问题标题】:How to reduce many similar correlated subqueries?如何减少许多相似的相关子查询?
【发布时间】:2011-09-29 05:08:20
【问题描述】:

这是一个更大的声明的一部分,但我想知道 CTE 或其他方法是否有助于提高效率或更清洁。我可以将它写成一个表值函数并将其包含在我的 from 子句中,但如果有其他解决方案,我想避免使用额外的对象。

这里的SELECT TOP 1 ... 子查询只是捕捉到我的汇率的生效日期早于基表,但我不喜欢为我需要访问的每一列重复它们。有没有更好的方法来实现这一点,或者这是一个正常的陈述?

SELECT j.EmployeeId
       ,j.CompanyId
       ,j.JobCode
       ,COALESCE(j.CustomWageRate, r.WageRate, (SELECT TOP 1 WageRate
                                                FROM   ContractLabor.CompanyJobRates
                                                WHERE  CompanyId = j.CompanyId
                                                       AND JobCode = j.JobCode
                                                       AND EffectiveDate < j.EffectiveDate
                                                ORDER  BY EffectiveDate DESC), 0) AS EffectiveRate
       ,COALESCE(r.CustomBurdenRateReg, (SELECT TOP 1 CustomBurdenRateReg
                                         FROM   ContractLabor.CompanyJobRates
                                         WHERE  CompanyId = j.CompanyId
                                                AND JobCode = j.JobCode
                                                AND EffectiveDate < j.EffectiveDate
                                         ORDER  BY EffectiveDate DESC)) AS CustomBurdenRateReg
       ,COALESCE(r.CustomBurdenRateOvt, (SELECT TOP 1 CustomBurdenRateOvt
                                         FROM   ContractLabor.CompanyJobRates
                                         WHERE  CompanyId = j.CompanyId
                                                AND JobCode = j.JobCode
                                                AND EffectiveDate < j.EffectiveDate
                                         ORDER  BY EffectiveDate DESC)) AS CustomBurdenRateOvt
       ,COALESCE(r.CustomBurdenRateDbl, (SELECT TOP 1 CustomBurdenRateDbl
                                         FROM   ContractLabor.CompanyJobRates
                                         WHERE  CompanyId = j.CompanyId
                                                AND JobCode = j.JobCode
                                                AND EffectiveDate < j.EffectiveDate
                                         ORDER  BY EffectiveDate DESC)) AS CustomBurdenRateDbl
       ,j.EffectiveDate
FROM   ContractLabor.EmployeeJobDetails j
       LEFT JOIN ContractLabor.CompanyJobRates r
         ON j.CompanyId = r.CompanyId
            AND j.JobCode = r.JobCode
            AND j.EffectiveDate = r.EffectiveDate

【问题讨论】:

    标签: sql sql-server sql-server-2005 subquery correlated-subquery


    【解决方案1】:
    SELECT j.EmployeeId
           ,j.CompanyId
           ,j.JobCode
           ,COALESCE(j.CustomWageRate, r.WageRate, ca.WageRate, 0) AS EffectiveRate
           ,COALESCE(r.CustomBurdenRateReg, ca.CustomBurdenRateReg) AS CustomBurdenRateReg
           ,COALESCE(r.CustomBurdenRateOvt, ca.CustomBurdenRateOvt) AS CustomBurdenRateOvt
           ,COALESCE(r.CustomBurdenRateDbl, ca.CustomBurdenRateDbl) AS CustomBurdenRateDbl
           ,j.EffectiveDate
    FROM   ContractLabor.EmployeeJobDetails j
           LEFT JOIN ContractLabor.CompanyJobRates r
             ON j.CompanyId = r.CompanyId
                AND j.JobCode = r.JobCode
                AND j.EffectiveDate = r.EffectiveDate
    
           OUTER APPLY --or CROSS APPLY
           (
                SELECT TOP 1 WageRate
                        ,CustomBurdenRateReg
                        ,CustomBurdenRateOvt
                        ,CustomBurdenRateDbl
                FROM   ContractLabor.CompanyJobRates
                WHERE  CompanyId = j.CompanyId
                        AND JobCode = j.JobCode
                        AND EffectiveDate < j.EffectiveDate
                ORDER  BY EffectiveDate DESC       
           ) ca  
    

    【讨论】:

    • 啊,好多了。 OUTER APPLY 是我不知道要寻找的缺失部分。谢谢。
    • 不客气。您可以使用SET STATISTICS IO ON 查看这两个查询完成了多少逻辑和物理读取。越少越好。 Using APPLY.
    【解决方案2】:

    您可以使用 cross apply / top 1 在外部查询中加入派生表表达式,并一次选择所有相关列。

    您的查询可能如下所示:

    SELECT ..., ISNULL(x, defaultValues.x)
    FROM ...
      CROSS APPLY (SELECT TOP(1) x, y, z FROM ... WHERE ... ORDER BY ...) defaultValues
    

    这样会更有效,因为查询中的连接更少(您原来的每个相关子查询都会变成一个外连接)。

    您还可以将 OUTER APPLY 用于类似外部连接的功能。

    【讨论】:

    • 谢谢。是的,OUTER APPLY 在这种情况下对我有用。
    猜你喜欢
    • 2015-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多