在与变量

时间:2019-01-17 13:18:30

标签: sql-server tsql variables case

我有一个SELECT语句,在其中定义了CASE表达式,该表达式在同一SELECT内的其他计算中使用。但是,这是一个很大的案例,所以我不想一直复制它。是否可以将其定义为变量,然后在计算中仅使用变量名称?

例如:

CASE WHEN xxxx END AS - define it as @test
then use it for example in WHERE part - WHEN @test='X'

有可能吗?谢谢

3 个答案:

答案 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可以防止优化器执行两次相同的计算。

enter image description here

答案 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子句中使用大小写。