游标与While循环-SQLServer
假设我在数据库中有一堆行(本例中是SQLServer2008),可以用来创建方程游标与While循环-SQLServer,sql,sql-server,Sql,Sql Server,假设我在数据库中有一堆行(本例中是SQLServer2008),可以用来创建方程 ----------------------------------------------------- OperationID | EquationID | Operation | Amount | Order ----------------------------------------------------- 1 | 1 | + | 12
-----------------------------------------------------
OperationID | EquationID | Operation | Amount | Order
-----------------------------------------------------
1 | 1 | + | 12 | 1
2 | 1 | + | 12 | 2
3 | 2 | / | 2 | 3
4 | 2 | + | 12 | 1
5 | 2 | - | 2 | 2
-----------------------------------------------------
我需要想出一个方法来计算这张表中的方程式
方程1:12+12=24方程2:(12-2)/2=5 我想不出一种不遍历行就能得到这些结果的方法。我知道的唯一方法是使用游标或使用临时表和while循环。有没有更好的方法?如果不是一般情况下,什么将执行更好的游标或while循环
注意:这有点简化,在项目的这个阶段,我们只能猜测数据会是什么样子。假设每个“方程”将有大约100到1000个运算,每天将有几千个“方程”需要处理。已经证明,递归CTE在计算运行总数方面比循环性能更好。这只是一个带有可变运算符的运行总数,因此性能优势应该适用于这里 创建行为类似于循环的递归CTE的方法如下:
;WITH cte AS (
SELECT equation, number, order FROM table WHERE order = 1
UNION ALL
SELECT table.equation,
CASE WHEN table.operation = '+' THEN cte.number + table.number
WHEN table.operation = '-' THEN cte.number - table.number END AS number, --etc.
table.order FROM table INNER JOIN cte ON table.order = cte.order + 1 AND table.equation = cte.equation
)
SELECT equation, number, order
FROM cte
OPTION (MAXRECURSION 1000);
第一个SELECT获取最左边的数字,UNION all对其返回的数字执行以下操作。maxrecursion选项将一个等式中的操作数限制为1000。当然,你可以把这个设定得更高
这个答案有些不完整,因为最终的select查询将返回中间结果。不过,这很容易过滤。我已经清理/充实了一些代码,并在这里介绍这些代码。我在社区维基上标记了这个答案,因为mootinator的答案值得称赞。这只是在不编辑答案的情况下呈现代码的最简单方式
declare @equations table (
OperationID int,
EquationID int,
Operation char(1),
Amount int,
[Order] int
)
insert into @equations
(OperationID, EquationID, Operation, Amount, [Order])
values
(1, 1, '+', 12, 1),
(2, 1, '+', 12, 2),
(3, 2, '/', 2, 3),
(4, 2, '+', 12, 1),
(5, 2, '-', 2, 2)
;with cteCalc as (
select EquationID, Amount, [Order]
from @equations
where [Order] = 1
union all
select e.equationid,
case when e.Operation = '+' then c.Amount + e.Amount
when e.Operation = '-' then c.Amount - e.Amount
when e.Operation = '*' then c.Amount * e.Amount
when e.Operation = '/' then c.Amount / e.Amount
end AS Amount,
e.[Order]
from @equations e
inner join cteCalc c
on e.EquationID= c.EquationID
where e.[Order] = c.[Order] + 1
),
cteMaxOrder as (
select EquationID, MAX([Order]) as MaxOrder
from cteCalc
group by EquationID
)
select c.EquationID, c.Amount
from cteMaxOrder mo
inner join cteCalc c
on mo.EquationID = c.EquationID
and mo.MaxOrder = c.[Order]
order by c.EquationID
option (maxrecursion 1000)
如果您使用的是SQLServer2005+,那么可以使用递归CTE,使用大小写来表示+、-、/,或者*我想,括号是如何处理的?是基于顺序列完成的吗?你怎么知道括号应该放在哪里?我最初的想法是,在插入到这个结构之前,你可能有一个“格式良好”的方程,所以我想问你为什么不能完整地存储方程?您可以始终将其参数化(例如“(@p1-@p2)/@p3”),以允许在执行时分配值。更简单…更简单=好:)是的,括号基于顺序列。在这个简化的示例中,我可以存储完整的公式,但实际的“公式”将有数千个操作和周期性添加的操作。最终查询如何返回中间结果?如果我只选择所有结果,例如,它将返回:等式:1 Order:1 Number:12和Order:2 Number:24。这个例子更像是一个只需要实际总数的运行总数。当然,如果你只想得到一个等式的结果,你可以选择TOP 1,其中等式=1 ORDER BY ORDER DESC+1我冒昧地把你的代码充实了一点。在社区维基上做了我的回答,因为你值得表扬。谢谢。我刚从SQLServer2000升级,所以我正在使用CTE经历一个“一切看起来都像钉子”的阶段。呵呵。