SQL:对列中的值执行算术运算

时间:2019-12-23 19:10:04

标签: sql sql-server

我有一个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。运算仅包括加法和减法。我该如何实现?很难从哪里开始。

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')