我有一个varchar
,其中包含一个公式:
declare @formula varchar(50) = 'X + Y + Z'
我还有一张桌子:
+---+---+
| A | B |
+---+---+
| X | 1 |
+---+---+
| Y | 2 |
+---+---+
| Z | 3 |
+---+---+
A列的值是唯一的,公式可能会更改。例如,如果公式设置为'X + Y + Z'
,则结果为6。如果公式设置为'Z - X + Y'
,则结果为4。运算仅包括加法和减法。我该如何实现?很难从哪里开始。
答案 0 :(得分:4)
SQL Server不支持宏替换,也没有Eval()...这会留下动态SQL
示例
Declare @YourTable Table ([A] varchar(50),[B] varchar(50))
Insert Into @YourTable Values
('X',1)
,('Y',2)
,('Z',3)
Declare @formula varchar(50) = 'X + Y + Z'
Select @formula=replace(@formula,[A],[B])
From @YourTable
Exec('Select NewValue='+@formula)
返回
NewValue
6
答案 1 :(得分:2)
只是为了好玩,这是一个经过修改的选项,它将支持TABLE
示例
Declare @YourValues Table ([A] varchar(50),[B] varchar(50))
Insert Into @YourValues Values
('X',1)
,('Y',2)
,('Z',3)
Declare @YourFormula Table (ID int,Formula varchar(50))
Insert Into @YourFormula Values
(1,'X + Y + Z'),
(2,'X - Y + Z')
Declare @SQL varchar(max) = stuff((Select concat(',(',ID,',',Formula,')') From @YourFormula For XML Path ('')),1,1,'')
Select @SQL=replace(@SQL,[A],[B])
From @YourValues
Create Table #TempResults (ID int,Calc money)
Exec('Insert Into #TempResults Select * from (values '+@SQL+')A(ID,Calc)')
Select * from #TempResults
返回
ID Calc
1 6.00
2 2.00
答案 2 :(得分:2)
这相当粗糙,仅适用于+/-操作数,但是,我相信它可以满足这个问题。
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
答案 3 :(得分:-1)
选择总和(B) 来自@table 在哪里('X','Y','Z')