Ответ 1
Отличный вопрос.
Я бы использовал выражение case, потому что:
- Есть только пять арифметических операторов.
- Вы не можете параметризовать арифметические операторы напрямую.
- Вы не можете выполнить динамический SQL inline.
Но есть альтернативы. Вы можете создать и выполнить динамический оператор SQL.
-- Query will be stored here.
DECLARE @Qry VARCHAR(255) = '';
-- Build up the query.
SELECT
@Qry =
@Qry
+ CASE ROW_NUMBER() OVER (ORDER BY cont_sal)
WHEN 1 THEN 'SELECT '
ELSE 'UNION ALL SELECT '
END
+ ''''
+ Expression
+ ''''
+ ' AS Expression,'
+ Expression
+ ' AS Result '
FROM
#test AS t
CROSS APPLY
(
-- Avoid typing expression twice.
SELECT
CAST(cont_sal AS VARCHAR(50))
+ ' '
+ operator
+ ' '
+ CAST(check_value AS VARCHAR(50)) AS Expression
) AS ex
;
-- Execute it.
EXECUTE(@Qry);
Или вы можете использовать крест для вычисления результата с использованием грубой силы.
SELECT
*
FROM
#test AS t
CROSS APPLY
(
VALUES
('+', cont_sal + check_value),
('-', cont_sal - check_value),
('*', cont_sal * check_value),
('/', cont_sal / NULLIF(check_value, 0)),
('%', cont_sal % NULLIF(check_value, 0))
) AS ex(operator, result)
WHERE
ex.operator = t.operator
;
Здесь вычисляется всякая возможная операция. Те, которые не требуются, отфильтровываются из набора результатов. Этот подход легче читать и писать, но выполняет вычисления, которые никогда не требуются. Тем не менее, это привело к созданию более быстрого плана запросов в моем динамическом примере.
ИЗМЕНИТЬ
Благодаря @Damien_The_Unbeliever, который указал на мою уязвимость для деления на нулевые ошибки. Я использовал NULLIF для замены 0s для нулей, что позволяет избежать ошибки.
Я только обновил второй пример.