在Transact-SQL中用CASE语句替换条件逻辑有效吗?

时间:2011-02-07 16:10:42

标签: sql-server query-optimization

我有一个类似的存储过程:

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的案例条件?

4 个答案:

答案 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)中基于过程的解决方案,您几乎总能获得更快的结果。