Tsql SQL Server:更新顺序,它为什么有效?我可以信任它吗?

Tsql SQL Server:更新顺序,它为什么有效?我可以信任它吗?,tsql,sql-server-2012,Tsql,Sql Server 2012,我正在使用SQL Server 2012 有一个神奇的查询,我不明白为什么它使用一个临时列,我正在更新一个表,让它使用它已经计算出的值 它将rolMul设置为到目前为止项目的滚动乘法 我能相信这种方法吗 为什么它首先起作用 如果我不能信任它,我可以使用什么替代方案 -创建要处理的数据 select * into #Temp from ( select 1 as id, null as rolMul ) A insert into #temp select 2 as id, null as rol

我正在使用SQL Server 2012

有一个神奇的查询,我不明白为什么它使用一个临时列,我正在更新一个表,让它使用它已经计算出的值

它将rolMul设置为到目前为止项目的滚动乘法

我能相信这种方法吗

为什么它首先起作用

如果我不能信任它,我可以使用什么替代方案

-创建要处理的数据

select * into #Temp from (
select 1 as id, null as rolMul ) A
insert into #temp select 2 as id, null as rolMul  
insert into #temp select 3 as id, null as rolMul 
insert into #temp select 4 as id, null as rolMul  
insert into #temp select 5 as id, null as rolMul  
---这就是魔法我不明白它为什么起作用---

declare @rolMul int = 1
update #temp set @rolMul = "rolMul" = @rolMul * id from #temp

select * from #temp 

-- you can see it did what I wanted multiply all the previous values

drop table #temp
困扰我的是:

它为什么有效?我能相信它能工作吗? 订单怎么样?如果 这张桌子没有订

从中选择*进入临时状态 选择3作为id,选择null作为ROLMULA 插入临时选择1作为id,空作为rolMul 插入temp select 5作为id,null作为rolMul 插入临时选择2作为id,空作为rolMul 插入临时选择4作为id,空作为rolMul

声明@rolMul int=1 从temp更新温度集@rolMul=rolMul=@rolMul*id

按id从临时订单中选择* 升降台温度

如果我不能信任它,我可以使用什么替代方案

从SQL Server 2012开始,您可以使用有效的对数滚动和

WITH tempcte AS (
  SELECT
    id,
    rolmul,
    EXP(SUM(LOG(id)) OVER (ORDER BY id)) AS setval
  FROM #Temp
)
UPDATE tempcte
SET rolmul = setval;
SQL Server 2012将子句引入函数。通过一个简单的例子说明了如何有效地解决运行总问题

表示两个数乘积的对数等于每个数的对数之和

这个恒等式允许我们使用快速和以相似的速度计算乘法。在求和之前取对数,然后取结果的指数,你就得到了答案

SQL Server为您提供了计算基数e及其指数的和。只要你是始终如一的,你使用什么基础并不重要

这是必需的,因为窗口表达式不能出现在update语句的SET子句中

对于少量行,查询是可靠正确的,但会很快溢出。尝试64行2,你会打破bigint


理论上,只要ID是唯一的,就应该产生正确的结果。实际上,我认为您的ID集总是很小的:-

。这里所说的内容适用于您的案例,我们将在这里介绍,除了SQL Server 2012中没有可以使用的内置聚合之外。结论是不要相信奇怪的更新,使用光标。米凯尔,这也是我的想法,但看起来很诱人。@marc_这也是我的想法。但它看起来很有希望。它的运行速度比游标快得多,也许我可以添加聚集索引什么的?如果我在临时id上添加createclusterendextempid;它在未排序的情况下也能工作,但我害怕在生产环境中使用它:@MikaelEriksson从SQL Server 2012开始,您可以通过运行对数和来实现这一点:EXPSUM LOGnum OVER ORDER by num给出正确的结果,而无需调用quirks.Nice。出于性能原因,您应该将over子句更改为over ORDER BY id rows UNBONDED PREVICE。默认值为range unbounded previous,由于重复id值的行为不同,因此在进行求和时必须使用工作表作为中间值。使用行时,SQL Server只在内存中保留一个值,即到目前为止的总和,并使用该值。要确认我在这一点上是正确的,您可以进行测试并查看读取。统计IO显示,两者都有一个工作表,但前面的无界行有0个额外读取。有趣的实际上,只有id唯一时,查询才能正常工作。否则,rolmul列会悄悄地为每个列累加一个和,然后跳到id的下一个增量。我想我还有很多关于窗口函数的知识要学习。@MikaelEriksson在得到足够的行之前,很长一段时间你就会遇到这个查询的数字溢出-EXPSUMLOG是为值执行mul的一种很好的方法。但我最初使用Mul只是为了显示一个SQL中不存在的函数。我的实际问题不是Mul,而是某种函数可以使用多个变量。。。