如何在SQL中保持滚动校验和?

如何在SQL中保持滚动校验和?,sql,tsql,Sql,Tsql,我试图保持一个滚动校验和,以说明顺序,所以采取以前的'校验和'和异或它与当前的一个,并生成一个新的校验和 Name Checksum Rolling Checksum ------ ----------- ----------------- foo 11829231 11829231 bar 27380135 checksum(27380135 ^ 11829231) = 93291803 baz 96326587

我试图保持一个滚动校验和,以说明顺序,所以采取以前的'校验和'和异或它与当前的一个,并生成一个新的校验和

Name      Checksum     Rolling Checksum
------    -----------  -----------------
foo       11829231     11829231
bar       27380135     checksum(27380135 ^ 11829231) = 93291803
baz       96326587     checksum(96326587 ^ 93291803) = 67361090
我怎样才能完成这样的事情

请注意,这些计算完全是虚构的,仅用于说明

Select Name, Checksum
    , (Select T1.Checksum_Agg(Checksum)
        From Table As T1
        Where T1.Name < T.Name) As RollingChecksum
From Table As T
Order By T.Name
要进行滚动操作,您需要对行进行一些类似于订单的操作。可以是名称、整型键、日期或其他。在我的示例中,我使用了name,即使示例数据中的顺序不是字母顺序。此外,我正在SQL中使用函数


此外,您最好有一个唯一的值,用于比较内部查询和外部查询。例如,对于整数键或甚至字符串键,T1.PK我不确定滚动校验和,但对于滚动校验和,例如,您可以使用UPDATE命令执行此操作:

declare @a table (name varchar(2), value int, rollingvalue int)
insert into @a
    select 'a', 1, 0 union all select 'b', 2, 0 union all select 'c', 3, 0 

select * from @a

declare @sum int
set @sum = 0

update @a
set @sum =  rollingvalue = value + @sum 

select * from @a
这基本上就是问题所在

编辑:

我最初的主张是,这是为数不多的基于光标的解决方案实际上表现最好的地方之一。三角形自连接解决方案的问题在于,它将重复计算与下一步的子计算相同的累积校验和,因此,由于所需的工作量随行数呈指数增长,因此不具有很强的可扩展性

科琳娜的回答使用了古怪的更新方法。我已经调整它来做校验和,在我的测试中发现光标解决方案用了3秒而不是26秒。两者都产生了相同的结果。然而不幸的是,它依赖于未记录的更新行为。在决定是否在生产代码中依赖它之前,我肯定会阅读讨论

第三种可能是使用CLR描述的,我没有时间测试。但从这一点来看,似乎很有可能在显示时计算running total类型的内容,但当必须保存计算结果时,光标会执行这些操作

CREATE TABLE TestTable
(
PK int identity(1,1) primary key clustered,
[Name] varchar(50),
[CheckSum] AS CHECKSUM([Name]),
RollingCheckSum1 int NULL,
RollingCheckSum2 int NULL
)


/*Insert some random records (753,571 on my machine)*/
INSERT INTO TestTable ([Name])
SELECT newid() FROM sys.objects s1, sys.objects s2, sys.objects s3
方法一:基于文章

方法二——使用与Hugo Kornelis在该文章讨论中主张的相同的游标选项

SET NOCOUNT ON
BEGIN TRAN

DECLARE @RCS2 INT
DECLARE @PK INT, @CheckSum INT

DECLARE curRollingCheckSum CURSOR LOCAL STATIC READ_ONLY
    FOR
    SELECT PK, [CheckSum]
    FROM         TestTable
    ORDER BY PK

   OPEN curRollingCheckSum

  FETCH NEXT FROM curRollingCheckSum
   INTO @PK, @CheckSum

  WHILE @@FETCH_STATUS = 0
  BEGIN

  SET @RCS2 = CASE WHEN @RCS2 IS NULL THEN @CheckSum ELSE CHECKSUM(@CheckSum ^ @RCS2) END


 UPDATE dbo.TestTable 
    SET RollingCheckSum2 = @RCS2
  WHERE @PK = PK

  FETCH NEXT FROM curRollingCheckSum
   INTO @PK, @CheckSum

    END

COMMIT
测试它们是否相同

SELECT * FROM TestTable
WHERE RollingCheckSum1<> RollingCheckSum2

@Martin Smith—这不是很大程度上取决于您使用什么来匹配内部和外部查询吗?也就是说,如果比较是T1.PKSELECT * FROM TestTable WHERE RollingCheckSum1<> RollingCheckSum2