我正在尝试保持滚动校验和以考虑订单,因此请使用之前的“校验和”并将其与当前的校验和进行xor并生成新的校验和。
Name Checksum Rolling Checksum
------ ----------- -----------------
foo 11829231 11829231
bar 27380135 checksum(27380135 ^ 11829231) = 93291803
baz 96326587 checksum(96326587 ^ 93291803) = 67361090
我将如何完成这样的事情?
(请注意,计算完全弥补,仅供参考)
答案 0 :(得分:2)
这基本上是running total问题。
修改强>
我最初声称这是基于光标的解决方案实际上表现最佳的少数几个地方之一。三角形自连接解决方案的问题在于它将重复地重新计算与下一步的子计算相同的累积校验和,因此随着所需工作随行数呈指数增长而不能很大程度地扩展。
Corina的回答使用了“古怪的更新”方法。我调整它来做校验和,在我的测试中发现光标解决方案需要3秒而不是26秒。两者都产生了相同的结果。不幸的是,它依赖于Update行为的无证方面。在决定是否在生产代码中依赖于此之前,我肯定会阅读讨论here。
第三种可能性描述here(使用CLR)我没有时间测试。但是从the discussion here开始计算运行总类型事物似乎是一种很好的可能性,但是当计算结果必须保存回来时,光标会执行输出。
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
方法一:基于Jeff Moden文章
DECLARE @RCS int
UPDATE TestTable
SET @RCS = RollingCheckSum1 =
CASE WHEN @RCS IS NULL THEN
[CheckSum]
ELSE
CHECKSUM([CheckSum] ^ @RCS)
END
FROM TestTable WITH (TABLOCKX)
OPTION (MAXDOP 1)
方法二 - 使用与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
答案 1 :(得分:1)
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
要进行滚动操作,您需要对行的顺序有一些相似之处。这可以是名字,整数键,日期或其他。在我的示例中,我使用了名称(即使示例数据中的顺序不是按字母顺序排列的)。另外,我在SQL中使用Checksum_Agg函数。
此外,理想情况下,您可以使用唯一值来比较内部和外部查询。例如,Where T1.PK < T.PK
对于整数键或甚至字符串键都可以正常工作。在我的解决方案中,如果Name
具有唯一约束,那么它也可以运行得很好。
答案 2 :(得分:1)
我不确定滚动校验和,但是对于滚动总和,您可以使用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