如何减少许多相似的相关子查询?
Posted
技术标签:
【中文标题】如何减少许多相似的相关子查询?【英文标题】: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
【问题讨论】:
【参考方案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
在这种情况下对我有用。以上是关于如何减少许多相似的相关子查询?的主要内容,如果未能解决你的问题,请参考以下文章