我试图快速确定两组时间表是否相同,并生成一个可以引用这些独特时间表的密钥。我最初尝试使用 HASHBYTES,但很快发现您只能散列 8000 个字符,而且我有大量的日期时间,当它们连接时超过 8000。
因此,我尝试使用 Checksum 和 Checksum_Agg,因为它们似乎是为这类事情设计的。我知道校验和更有可能生成非唯一值。但是我需要将它们相互比较的范围/上下文太窄了,我想我可以侥幸逃脱。
不幸的是,经过一点点测试后,我了解到我可以在 4 行日期时间数据中找到校验和“冲突”!我觉得这有点奇怪,并发现了碰撞的模式。
下面是一个演示该问题的示例脚本:
声明@Rows 表 ( [GroupId] 整数, [开始日期] 日期时间, [结束日期] DATETIME ) --Group1 插入@Rows 值(1、'2013-01-20 01:00:00.000'、'2013-01-20 01:20:00.000') 插入@Rows 值(1,'2013-01-20 01:20:00.000','2013-01-20 01:40:00.000') --INSERT INTO @Rows 值 (1, '2013-01-20 01:40:00.000', '2013-01-20 02:00:00.000') --INSERT INTO @Rows 值 (1, '2013-01-20 02:00:00.000', '2013-01-20 02:20:00.000') --INSERT INTO @Rows 值 (1, '2013-01-20 02:20:00.000', '2013-01-20 02:40:00.000') --INSERT INTO @Rows 值 (1, '2013-01-20 02:40:00.000', '2013-01-20 03:00:00.000') --Group2 插入@Rows 值(2、'2013-01-21 01:00:00.000'、'2013-01-21 01:20:00.000') 插入@Rows 值(2、'2013-01-21 01:20:00.000'、'2013-01-21 01:40:00.000') --INSERT INTO @Rows 值 (2, '2013-01-21 01:40:00.000', '2013-01-21 02:00:00.000') --INSERT INTO @Rows 值 (2, '2013-01-21 02:00:00.000', '2013-01-21 02:20:00.000') --INSERT INTO @Rows 值 (2, '2013-01-21 02:20:00.000', '2013-01-21 02:40:00.000') --INSERT INTO @Rows 值 (2, '2013-01-21 02:40:00.000', '2013-01-21 03:00:00.000') 选择 [ChecksumAgg1] = CHECKSUM_AGG([CheckSum]) 从 ( 选择 [校验和] = 校验和([开始日期],[结束日期]) 来自@Rows 其中 GroupId = 1 ) G1 选择 [ChecksumAgg2] = CHECKSUM_AGG([CheckSum]) 从 ( 选择 [校验和] = 校验和([开始日期],[结束日期]) 来自@Rows 其中 GroupId = 2 ) G2
结果是:
校验和Agg1:5681728
校验和Agg2:5681728
这两个日期系列之间的唯一区别是它们相隔 1 天。但是它们会生成相同的校验和!但仅当行数为偶数时。如果您取消注释 Group 1 中的 INSERT 和 Group 2 中的一个 INSERT,您将获得两个不同的校验和。但是然后取消评论另一对,您将获得另一场比赛!
最后我有两个问题。我很想更多地了解它是如何工作的,以及为什么这种模式似乎会影响一个相当可预测的校验和值。更重要的是,我想知道是否有更好的方法来创建大量数据的“指纹”。我知道我不能保证这个哈希是全球唯一的,但我显然需要比校验和更好的东西。
我能够欺骗校验和计算的一种方法是在 Datetime 上执行 HASHBYTES,然后将其提供给 Checksum 函数。通过这种方式,校验和被提供的值比一组具有相似外观差异的日期看起来更随机。但这足够了吗?
编辑-这里只是更多的上下文。
基本上我有一个系统,它有大量的时间表数据和一个单独的系统,它在特定时间对这些时间表感兴趣。例如,多个用户可能会看到这个复杂时间表的某个部分的特定版本,并希望添加一些元数据(可能是他们的批准状态、注释或其他内容)。如果某些外部来源对任何单个日期时间进行了更改,则需要断开此链接,因为它不再是相同的时间表!
有许多不同的系统可以对核心调度数据进行更改,这就是为什么我很难将这种担忧提升到代码级别,以便以某种方式管理并将其“规范化”为以某种方式表示每个快照的实体。我必须在一百万个地方安装挂钩来监听变化,然后清理任何指向时间表的东西。