我上,我需要根据另一列SQL查询中使用列一个公式来计算值
以下规定的公式计算值的请求的工作是我的表:
我需要编写查询以获取将基于FORMULA
列的值。例如,我需要得到作为
由于公式可以是任何东西,包括我的专栏PRICE
和SIZE
的,我怎么写的查询来实现这一目标?
我上,我需要根据另一列SQL查询中使用列一个公式来计算值
以下规定的公式计算值的请求的工作是我的表:
我需要编写查询以获取将基于FORMULA
列的值。例如,我需要得到作为
由于公式可以是任何东西,包括我的专栏PRICE
和SIZE
的,我怎么写的查询来实现这一目标?
另一个相对容易做的选择是使用CLR。您可以利用DataTable的计算方法在C#中提供简单的一行代码。
[Microsoft.SqlServer.Server.SqlFunction]
public static double Evaluate(SqlString expression)
{
return double.Parse((new DataTable()).Compute(expression.ToString(), "").ToString());
}
然后将组件添加到SQL Server和创建包装函数:
CREATE FUNCTION [dbo].[Evaluate](@expression [nvarchar](4000))
RETURNS [float] WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [YourAssemblyName].[YourClassName].[Evaluate]
GO
现在你可以调用该函数作为一个简单的select语句的一部分:
SELECT itemid, price, size, formula,
dbo.Evaluate(REPLACE(REPLACE(formula, 'PRICE', FORMAT(price,'0.00')),
'SIZE', FORMAT(size, '0'))) as calcvalue FROM YourTable
解决方案为我工作..仍然不确定表现 – Rohaan
很高兴有帮助。根据我的经验,CLR函数非常快,但是我从来不需要在桌面上使用超过60-70,000条记录,所以我真的不想说最快的解决方案。我恐怕我非常喜欢这所学校“不修补,什么都不坏”。如果我找到适合我的解决方案,我倾向于不去寻找另一个:-) –
动态查询(唯一)的路要走,它并不复杂,你可以使用的情况下:
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
,而不是出现在多个行
EDIT2UNION ALL
因为同一个公式的打算: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);
我做与此类似的东西,如果你在一个较小的操作池中玩,这并不难。我去了一个系列,我有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语句令牌另一个表。你甚至可以将这个潜在的复杂化,如果你想做多次传递,你可以添加一个'组'列和一个'序列'并且一个接一个地完成。这取决于你的'公式'变得多么困难。因为如果进入频繁更改频繁更改的3个或4个变量,则可能需要执行动态SQL。但是,如果他们只是一些事情,那应该不那么难。请记住,这种方法的缺点在于,它在某个级别上很难编码,而且灵活性强,参数可以反复应用这个公式。
没有简单的方法来做到这一点。一种方法是使用游标和动态SQL。 –
更新期间为什么不在表中将值设置为计算列?如果更新发生不在SQL中 – ASpirin
即使在SQL中,例如onupdate触发器也可以运行动态sql来计算值并放入列 – ASpirin