This is rather crude and only works for +/- operands, however, I believe it satisfies the question.
DECLARE @Formulas TABLE (Formula NVARCHAR(MAX))
INSERT INTO @Formulas SELECT 'Z-X+Y'
DECLARE @Values TABLE(Name NVARCHAR(50), Value DECIMAL(18,2))
INSERT @Values VALUES ('X',1),('Y',2),('Z',3)
;WITH MySplitFormula AS
(
SELECT Value = SUBSTRING(Formula,Number,1) FROM @Formulas
CROSS APPLY (SELECT DISTINCT number FROM master..spt_values WHERE number > 0 AND number <= LEN(Formula))V
)
,NormalizedFormula AS
(
SELECT
DerivedOperations = CASE WHEN F.Value IN('+','-') THEN F.Value ELSE NULL END,
IsOperator = CASE WHEN F.Value IN('+','-') THEN 1 ELSE 0 END,
DerivedValues = CASE WHEN F.Value IN('+','-') THEN NULL ELSE V.Value END
FROM
MySplitFormula F
LEFT OUTER JOIN @Values V ON V.Name = F.Value
WHERE
NOT F.Value IS NULL
),
ValidatedFormula AS
(
SELECT DerivedOperations,DerivedValues FROM NormalizedFormula WHERE NOT((DerivedOperations IS NULL) AND (DerivedValues IS NULL))
),
Operators AS
(
SELECT
OrderIndex=ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
Operator=DerivedOperations FROM ValidatedFormula WHERE NOT DerivedOperations IS NULL
),
Operands AS
(
SELECT
OrderIndex=ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
Operand=DerivedValues FROM ValidatedFormula WHERE NOT DerivedValues IS NULL
)
,Marked AS
(
SELECT
OP.OrderIndex,
DoOperation = CASE WHEN OP.OrderIndex % 2 = 1 THEN 1 ELSE 0 END,
Operand1 = Operand,
Operator,
Operand2 = LEAD(Operand) OVER(ORDER BY OP.OrderIndex)
FROM
Operands OP
LEFT OUTER JOIN Operators OPR ON OPR.OrderIndex = OP.OrderIndex
)
,MarkedAgain AS
(
SELECT
*,
CalculatedValue = CASE WHEN DoOperation = 1 THEN
CASE
WHEN Operator = '+' THEN Operand1 + Operand2
WHEN Operator = '-' THEN Operand1 - Operand2
WHEN Operator IS NULL THEN
CASE WHEN LAG(Operator) OVER(ORDER BY OrderIndex) ='+' THEN Operand1 ELSE -Operand1 END
ELSE NULL
END
END
FROM
Marked
)
SELECT SUM(CalculatedValue) FROM MarkedAgain