SQL 服务器 CHECKSUM 函数问题

SQL Server CHECKSUM function issue

谁能给我解释一下,也许可以提出更好的方法。

为什么校验和(0.0280) = 校验和(-0.0280)? 强制转换为浮动会解决它,但我不愿意这样做,我宁愿想办法解决这个问题。

LE:我试图让事情保持简单,就像这里的大多数问题一样,这是在生产中出现的问题,把整个数据库结构放在一起有点矫枉过正。 我会尝试更好地解释它。我有一些动态结构 tables(在最终用户通过 Web 应用程序控制结构的意义上是动态的)具有以下粗略结构:Id (int)、StartDate、FKey1 (nvarchar)、Value1(十进制或nvarchar 或 int),Value2 ... ValueN。

这个 table 可以(同样由最终用户)填充冗余数据(数百万行),在一些计算过程中我想整理这个 table 只留下相关信息.整理它的方法是删除连续的相同行(日期除外)。为了性能,我想避免单独检查每一列,所以 CHECKSUM 派上用场了,因为它也支持多列作为输入。

如果您认为每个可能的 CHECKSUM 都只有一个可能值,那您就错了。

来自documentation

If at least one of the values in the expression list changes, the list checksum will probably change. However, this is not guaranteed. Therefore, to detect whether values have changed, we recommend use of CHECKSUM only if your application can tolerate an occasional missed change. Otherwise, consider using HashBytes instead. With a specified MD5 hash algorithm, the probability that HashBytes will return the same result, for two different inputs, is much lower compared to CHECKSUM.

如果您想进一步研究它,您可以Google CHECKSUM collisions

使用散列函数(如 CHECKSUM)总会有冲突的风险。

您可以尝试另一个(较慢的)哈希函数(如@TabAlleman 提到的 HashBytes),或者您可以尝试一些自制的尝试,这些尝试可能比 HashBytes 表现更好(但这应该经过测试),并且更适合你对你期望的数字的预期。所以这是一个权衡:性能与碰撞风险。这里有 2 个这样的自制尝试,对于除符号外相等的数字,它们会给出不同的结果。请注意,这些变体也会产生碰撞,但很可能是因为其他差异而不仅仅是它们的符号。

select checksum(.028, floor(.28))
select checksum(-.028, floor(-.28))

select checksum(.028) + sign(.28)
select checksum(-.028) + sign(-.28)

你说可以转成float来解决,但还是不想做,不知道是不是出于性能的考虑。如果是这样,我不确定我的变体是否会比转换为浮点数表现得更好。自己测量一下吧:-)