Я знаю, как установить отрицательное значение в ноль:
select case when (formula) < 0 then 0 else (formula) end as result from tab
Но что, если «формула» — очень длинная формула? Тогда я должен ввести его дважды. Есть ли способ добиться того же результата, не вводя формулу дважды?
Мой реальный случай выглядит так:
select
sum
(
case when
(t1.x + t2.x + t3.x) * t4.p - (t5.x + t6.x + t7.x) * t8.p ) < 0
then 0
else
(t1.x + t2.x + t3.x) * t4.p - (t5.x + t6.x + t7.x) * t8.p )
end
) as result
from
t1
left join t2 on t1.x = t2.x
left join t3 on t1.x = t3.x
... etc ....
t2, t3, t4 и т. д. исходят из операторов cte, которые предоставляют значения для определенных учетных записей.
Вы можете попробовать следующие подходы:
VALUES
конструктор табличных значений и MAX
агрегатная функция.APPLY
оператор и MAX
агрегатная функция.T-SQL:
SELECT (SELECT MAX(result) FROM (VALUES (0), (tab.x)) v(result)) AS result
FROM (VALUES
(2 - 3),
(4 + 5)
) tab (x)
SELECT apl.result
FROM (VALUES
(2 - 3),
(4 + 5)
) tab (x)
CROSS APPLY (SELECT MAX(x) FROM (VALUES (0), (tab.x)) v (x)) apl (result)
Следующий пример, основанный на коде из вопроса, является возможным решением:
SELECT x INTO t1 FROM (VALUES (-1), (1)) v (x)
SELECT x INTO t2 FROM (VALUES (-1), (1)) v (x)
SELECT x INTO t3 FROM (VALUES (-1), (1)) v (x)
SELECT SUM(a.result)
FROM t1
LEFT JOIN t2 ON t1.x = t2.x
LEFT JOIN t3 ON t1.x = t3.x
CROSS APPLY (
SELECT MAX(x) FROM (VALUES (0), (t1.x + t2.x + t3.x)) v (x)
) a (result)
Используйте CTE.
DECLARE @Table1 TABLE
(
ID INT,
A INT,
B INT
);
DECLARE @Table2 TABLE
(
ID INT,
C INT,
D INT
);
INSERT @Table1 VALUES
( 1, 1, 2),
( 2, 3, -4),
( 3, -5, -6);
INSERT @Table2 VALUES
( 1, -7, 8),
( 2, 9, 10),
( 3, 11, 12);
WITH query (Formula)
AS
(
SELECT (A + B) * (C - D) AS Formula
FROM @Table1 T1 INNER JOIN @Table2 T2 ON T1.ID = T2.ID
)
SELECT Formula, CASE WHEN Formula < 0 THEN 0 ELSE Formula END AS Result
FROM query
Результат:
Это можно сделать с помощью простого подзапроса, например.
select
sum
(
case when ForumulaResult < 0
then 0
else ForumulaResult
end
) as result
from (
select
(t1.x + t2.x + t3.x) * t4.p - (t5.x + t6.x + t7.x) * t8.p) as ForumulaResult
from t1
left join t2 on t1.x = t2.x
left join t3 on t1.x = t3.x
-- ... etc ....
) x;
Или с помощью cross apply
select
sum
(
case when ForumulaResult < 0
then 0
else ForumulaResult
end
) as result
from t1
left join t2 on t1.x = t2.x
left join t3 on t1.x = t3.x
cross apply (select (t1.x + t2.x + t3.x) * t4.p - (t5.x + t6.x + t7.x) * t8.p ) as ForumulaResult) x
Или используя CTE, как уже показано... хотя вы указываете, что у вас уже есть CTE, генерирующий начальные данные... так что это может быть сложнее объединить.
На первый взгляд, с простыми данными, предоставленными @Han, все они создают один и тот же план выполнения, поэтому выбор того, что использовать, на самом деле зависит от того, какой из них более понятен для вас.
Спасибо, подзапрос теперь мой путь. подход перекрестного применения также очень интересен.