如何减少许多类似的相关子查询?

时间:2011-09-29 05:08:20

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

这是一个更大声明的一部分,但我想知道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

2 个答案:

答案 0 :(得分:3)

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  

答案 1 :(得分: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作为外连接功能。