далее использовать определенный CASE в том же SELECT, что и переменная - PullRequest
0 голосов
/ 17 января 2019

У меня есть оператор 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 голосов
/ 17 января 2019

Вы можете заключить запрос в подзапрос и поместить предложения 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.

0 голосов
/ 17 января 2019

Да, вы можете И это дает большие преимущества в производительности. Рассмотрим следующие примеры данных и запросов.

-- 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;

Как уже упоминалось, вы могли бы CROSS APPLY примерно так:

-- 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;

Обратите внимание, как я заменил все ссылки на оператор CASE на itvf.result . Код намного чище. Другое преимущество - это план выполнения. Использование CROSS APPLY таким образом не позволяет оптимизатору выполнить один и тот же расчет дважды.

enter image description here

0 голосов
/ 17 января 2019

Вы хотите что-то подобное:

select *
from . . .  cross apply
    ( values (case when . . .
                   then . . . 
                   else . . .
              end) 
    ) tt (test)
where tt.test = 'X'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...