SQL Server:更新顺序,为什么它可以工作,我可以信任吗?

时间:2014-04-13 14:03:48

标签: 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 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

困扰我的是:

  1. 为什么会这样?我可以信任它吗?
  2. 订单怎么样?如果 桌子没有订购

    从*中选择*进入#Temp 选择3作为id,null作为rolMul)A 插入#temp选择1作为id,null作为rolMul 插入#temp select 5作为id,null作为rolMul
    插入#temp select 2作为id,null作为rolMul
    插入#temp select 4作为id,null作为rolMul

    声明@rolMul int = 1 更新#temp set @rolMul =“rolMul”=来自#temp的@rolMul * id

    按ID从#temp顺序中选择* 删除表#Temp

1 个答案:

答案 0 :(得分:1)

  

如果我不相信它可以使用哪些替代品?

从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将OVER子句引入SUM函数。 Ole Michelsen以简短的示例展示了如何有效地解决运行中的总问题。

product law of logarithms表示两个数字的乘积的对数等于每个数字的对数之和。

这个标识允许我们使用快速和以相似的速度计算乘法。在总和之前记录日志并取结果的指数,你就得到答案了!

SQL Server为您提供LOGEXP来计算natural logarithm(base e )及其指数。只要你保持一致,你使用什么基础并不重要。

updatable common table expression是必要的,因为窗口表达式不会出现在更新语句的SET子句中。

对于少量行,查询可靠地正确,但会很快溢出。尝试64行2,你就会破坏bigint!

理论上,只要id是唯一的,就应该产生正确的结果。在实践中,我认为你的id组总是很小: - )