我有一个类似的存储过程:
IF @Param = '1'
SELECT HT.HeaderKey, HT.Description,
(SELECT SUM(E1) -- E1 is actually a complex expression
FROM DetailTable DT INNER JOIN ...
INNER JOIN ...
INNER JOIN ...
WHERE DT.HeaderKey = HT.HeaderKey)
FROM HeaderTable HT
ELSE IF @Param = '2'
SELECT HT.HeaderKey, HT.Description,
(SELECT SUM(E2) -- E2 is yet another complex expression
FROM DetailTable DT INNER JOIN ... -- Here, DetailTable is not
INNER JOIN ... -- joined to the same tables
INNER JOIN ... -- as in the first case
WHERE DT.HeaderKey = HT.HeaderKey)
FROM HeaderTable HT
-- Etc. There are five cases.
我希望将查询减少到以下内容:
SELECT HT.HeaderKey, HT.Description,
CASE @Param
WHEN '1'
(SELECT SUM(E1)
FROM DetailTable DT INNER JOIN ...
INNER JOIN ...
INNER JOIN ...
WHERE DT.HeaderKey = HT.HeaderKey)
WHEN '2'
(SELECT SUM(E2)
FROM DetailTable DT INNER JOIN ...
INNER JOIN ...
INNER JOIN ...
WHERE DT.HeaderKey = HT.HeaderKey)
-- Etc.
ELSE 0
END
FROM HeaderTable HT
但是,如果SQL Server评估所有案例,无论实际返回哪个案例,修改后的查询都将非常低效。
因此,我想知道,SQL Server是在CASE
语句中评估所有案例,还是只评估第一个满足CASE
的案例条件?
答案 0 :(得分:2)
不,它为计划添加了“passthru谓词”,确保它只评估必要的查询。见Subqueries in CASE Expressions
答案 1 :(得分:2)
如this article中所述,SQL Server的CASE语句确实利用了短路,因此在所示的示例中,它不会评估每行可能的每个CASE结果的结果。
但是,您仍然会获得比当前格式更低效的查询,因为您将强制所有结果共享相同的执行计划,这可能不是最佳的。根据CASE子查询之间的差异,效果可能非常显着。
答案 2 :(得分:0)
假设每个子查询中的连接相同,我会尝试这样的事情:
;with dt as
(
select
HeaderKey,
sum(case @Param
when 1 then E1
when 2 then E2
...) as ExpressionSum
from DetailTable DT
inner join...
group by dt.HeaderKey
)
select
ht.HeaderKey,
ht.description,
dt.ExpressionSum
from HeaderTable HT
inner join dt
on HT.HeaderKey=dt.HeaderKey
或者我可能会误解你正在尝试做什么;)
答案 3 :(得分:-1)
使用基于集合的解决方案与SQL Server(以及所有RDMS)中基于过程的解决方案,您几乎总能获得更快的结果。