Да, вы можете И это дает большие преимущества в производительности. Рассмотрим следующие примеры данных и запросов.
-- 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 таким образом не позволяет оптимизатору выполнить один и тот же расчет дважды.