1

这是一个更大的声明的一部分,但我想知道CTE或其他方法是否有助于提高效率或清洁度。我可以把它写成一个表值函数,并将其包含在我的from子句中,但如果有另一个解决方案,我想避免额外的对象。如何减少许多类似的相关子查询?

SELECT TOP 1 ...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 

回答

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 
+0

啊,好多了。 “外部应用”是我不知道寻找的缺失部分。谢谢。 – JustinStolle

+0

不客气。您可以使用“SET STATISTICS IO ON”来查看这两个查询完成了多少个逻辑和物理读取。越少越好。 [使用APPLY](http://msdn.microsoft.com/en-us/library/ms175156%28v=SQL.90%29.aspx)。 –

2

你可以使用跨应用/顶1,选择一次性全部相关列上加入一个派生表表达式中的外部查询。然后

您的查询可能看起来像:

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

这将是更有效,因为有较少的查询连接(每一个你原来的相关子查询的变成一个外部联接)。

您也可以使用OUTER APPLY作为外部联接功能。

+0

谢谢。是的,在这种情况下,“外部应用”适用于我。 – JustinStolle