我有一个SELECT
语句,在其中定义了CASE
表达式,该表达式在同一SELECT
内的其他计算中使用。但是,这是一个很大的案例,所以我不想一直复制它。是否可以将其定义为变量,然后在计算中仅使用变量名称?
例如:
CASE WHEN xxxx END AS - define it as @test
then use it for example in WHERE part - WHEN @test='X'
有可能吗?谢谢
答案 0 :(得分:2)
是的,您可以并且这样做具有很大的性能优势。请考虑以下样本数据和查询。
-- Sample data
IF OBJECT_ID('tempdb..#sometable') IS NOT NULL DROP TABLE #sometable;
CREATE TABLE #sometable(someid int identity, somevalue decimal(10,2));
INSERT #sometable(somevalue) VALUES (100),(1050),(5006),(111),(4);
-- Query:
DECLARE @var1 int = 100, @var2 int = 50, @var3 int = 900, @topPct tinyint = 90;
SELECT TOP (@topPct) PERCENT
someid,
somevalue,
someCalc =
CASE WHEN @var3 < somevalue THEN (@var1/(@var2*2.00))+@var3 ELSE @var3+somevalue END,
someRank = dense_rank() OVER (ORDER BY
CASE WHEN @var3 < somevalue THEN (@var1/(@var2*2.00))+@var3 ELSE @var3+somevalue END)
FROM #sometable
WHERE CASE WHEN @var3 < somevalue THEN (@var1/(@var2*2.00))+@var3 ELSE @var3+somevalue END
BETWEEN 900 AND 2000
ORDER BY -- simulate another event that causes a sort
CASE WHEN @var3 < somevalue THEN (@var1/(@var2*2.00))+@var3 ELSE @var3+somevalue END;
如上所述,您可以像这样交叉申请:
-- Improved
SELECT TOP (@topPct) PERCENT
s.someid, s.somevalue, someCalc=iTVF.result, someRank=DENSE_RANK() OVER (ORDER BY iTVF.result)
FROM #sometable AS s
CROSS APPLY (VALUES(CASE WHEN @var3 < somevalue THEN (@var1/(@var2*2.00))+@var3
ELSE @var3+somevalue END)) AS iTVF(result)
WHERE iTVF.result BETWEEN 900 and 2000
ORDER BY iTVF.result;
注意我如何用 itvf.result 替换CASE语句的所有引用。代码更简洁。另一个好处是执行计划。以这种方式使用CROSS APPLY可以防止优化器执行两次相同的计算。
答案 1 :(得分:1)
您想要这样的东西:
select *
from . . . cross apply
( values (case when . . .
then . . .
else . . .
end)
) tt (test)
where tt.test = 'X'
答案 2 :(得分:1)
您可以将查询包装在子查询中,然后将SELECT和WHERE子句放在子查询之外:
SELECT a, b, c, test
FROM (
SELECT a, b, c, CASE
WHEN ...
WHEN ...
END AS test
FROM ...
) AS sq
WHERE sq.test = 'something'
理想情况下,应避免在where子句中使用大小写。