如何在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
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.PK
SELECT * FROM TestTable
WHERE RollingCheckSum1<> RollingCheckSum2