我正在处理一项请求,我需要根据另一列中指定的公式计算值
以下是我的表格:
我需要编写查询以获取将基于FORMULA
列的值。例如,我需要结果
由于公式可以是由我的列PRICE
和SIZE
组成的任何内容,如何编写查询来实现此目标?
答案 0 :(得分:2)
动态查询是(唯一的)方式,它并不复杂:
DECLARE @query NVARCHAR(MAX) = '';
SELECT @query = @query + '
UNION
SELECT ItemID, Price, Size, Formula, ' + Formula + ' AS CalcValue FROM YourTable WHERE Formula = ''' + Formula + ''' '
FROM YourTable;
SET @query = STUFF(@query,1,8,'');
PRINT @query;
EXEC (@query);
但你必须意识到这是多么容易出错。如果“公式”列的值无效,则公式查询会中断。
修改:使用UNION
代替UNION ALL
,因为同一个公式出现在多行
edit2 :计划B - 不是运行一堆相同的选择查询并制作不同的结果,最好在开头制作不同的公式:
DECLARE @query NVARCHAR(MAX) = '';
WITH CTE_DistinctFormulas AS
(
SELECT DISTINCT Formula FROM YourTable
)
SELECT @query = @query + '
UNION ALL
SELECT ItemID, Price, Size, Formula, ' + Formula + ' AS CalcValue FROM YourTable WHERE Formula = ''' + Formula + ''' '
FROM CTE_DistinctFormulas;
SET @query = STUFF(@query,1,12,'');
PRINT @query;
EXEC (@query);
答案 1 :(得分:1)
另一种相对容易做到的选择是使用CLR。您可以利用DataTable的计算方法在C#中提供简单的一行代码。
Dim Excel
Dim xlBook
Dim xlSheet
Dim xyz
Set Excel = CreateObject("Excel.Application")
Set xlBook = Excel.Workbooks.Add
Set xlSheet = xlBook.Worksheets(1)
xlSheet.Application.Visible = 1
xlSheet.Application.Visible = True
xlSheet.Application.Cells(1, 1).Value = "This is column A, row 1"
xlSheet.Application.Cells(1, 2).Value = 200
xlSheet.Application.Cells(1, 3).Value = 0.1
xlSheet.Application.Cells(2, 2).Value = "=B1-190-C1"
Wscript.Echo "Like this?"
Wscript.Echo xlSheet.Application.Cells(1, 3)
Wscript.Echo xlSheet.Application.Range("B2")
xlSheet.Application.Range("B5").GoalSeek Goal=0, ChangingCell=xlSheet.Application.Range("B2")
xlSheet.SaveAs "C:\TEST.XLS"
xlSheet.Application.Quit
Set xlSheet = Nothing
然后将程序集添加到SQL Server并创建包装函数:
[Microsoft.SqlServer.Server.SqlFunction]
public static double Evaluate(SqlString expression)
{
return double.Parse((new DataTable()).Compute(expression.ToString(), "").ToString());
}
现在您可以将该函数作为简单select语句的一部分来调用:
CREATE FUNCTION [dbo].[Evaluate](@expression [nvarchar](4000))
RETURNS [float] WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [YourAssemblyName].[YourClassName].[Evaluate]
GO
答案 2 :(得分:0)
假设您需要使用的公式取决于列中的值,例如:大小,您可以使用案例
select price, size, when size= 2 then (price*1.2)/size
when size= 3 then price/size
end my_calc
from my_table
答案 3 :(得分:0)
我做了类似的事情,如果你在一个较小的操作池中玩,那就不那么难了。我选择了一个系列,其中我有X和Y列以及一个操作符。然后,我在关于识别运算符并基于此执行逻辑的语句时做了大量的案例。您可能需要稍微更改结构。问题的核心是SQL是一个基于结果集的引擎,所以你必须做一个操作来确定动态的任何东西都会变慢。 EG:
DECLARE @Formula TABLE
(
FormulaId INT IDENTITY
, FormulaName VARCHAR(128)
, Operator VARCHAR(4)
);
DECLARE @Values TABLE
(
ValueId INT IDENTITY
, FormulaId INT
, Price MONEY
, Size INT
)
INSERT INTO @Formula (FormulaName, Operator)
VALUES ('Simple Addition', '+'), ( 'Simple Subtraction', '-'), ('Simple Multiplication', '*'), ('Simple Division', '/'), ('Squared', '^2'), ('Grow by 20 percent then Multiply', '20%*')
INSERT INTO @Values (FormulaId, Price, Size)
VALUES (1, 10, 5),(2, 10, 5),(3, 10, 5),(4, 10, 5),(5, 10, 5),(6, 10, 5),(1, 16, 12),(6, 124, 254);
Select *
From @Values
SELECT
f.FormulaId
, f.FormulaName
, v.ValueId
, Price
, Operator
, Size
, CASE WHEN Operator = '+' THEN Price + Size
WHEN Operator = '-' THEN Price - Size
WHEN Operator = '*' THEN Price * Size
WHEN Operator = '/' THEN Price / Size
WHEN Operator = '^2' THEN Price * Price
WHEN OPerator = '20%*' THEN (Price * 1.20) * Size
END AS Output
FROM @Values v
INNER JOIN @Formula f ON f.FormulaId = v.FormulaId
使用这个方法我的操作实际上只是一个指向另一个表的指针引用,该表有一个操作符,它实际上只是用于我的case语句的所有意图和目的。你甚至可以将它复合化,如果你想要多次通过,你可以添加一个' Group'列和'序列'并一个接一个地做。这取决于你的公式'成为。因为如果经常更改操作符而导致频繁更改的3个或4个变量,那么您可能希望执行动态sql。但如果它们只是一些东西,那应该不会那么难。请记住,这种方法的缺点是它在某个级别上是硬编码的,但是灵活的参数可以反复应用这个公式。