避免在 SQL Server 的联接中使用复杂的字符串?

Cen*_*rze 2 join data-warehouse database-design sql-server t-sql

我将在 SQL Server 中为客户端创建几个表。对这个问题特别感兴趣的是FactStoreSale要创建表,并DimProduct在其中的第一个表将包括所有门店的销售情况,并包括例如StoreKeyDateKeyTimeKeyProductKey和销售数据。

DimProduct表将在关于产品,使用补充数据,即ProductNameProductGroupProductCategory等这个表将在价格等每个商店而言缓慢改变的尺寸和存储产品的历史。该表将包括列FromDateToDate,它们分别描述了输入数据的时间和替换数据的时间(默认值为 2999 年,ToDate直到插入产品的新更新)。

我相信这是很常见的。但是,ProductKeys来自底层数据库的非常复杂的字符串,例如140-xx4449CH-4.44,9.

在我看来,我的替代方案是Checksum在 SQL Server 中使用将复杂字符串转换为整数,并将它们存储在单独的列中,ProductKeyInt 并在执行 JOINS 时使用这些列。但是校验和不保证唯一的整数值,这可能会导致问题。当我在 Virtual PC 和我自己的 PC 上尝试 Checksum 时,对相同值执行 Checksum 会返回不同的结果,这也是一个问题。我相信这两者一起排除了校验和,除非可以以某种方式操纵它以使其更独特?

另一种选择是使用更复杂的函数来确保将字符串值转换为整数,例如在我的问题中提供的此处。诸如这样的解决方案但也有问题,该值100-xx31003将例如得到同样的结果。从某种意义上说,如果对 SQL 不那么精通的人需要尝试查找使用该函数的 Query 的任何问题,则可能很难理解正在发生的事情,这也很复杂。

我的第三个选择似乎是使用该DimProduct表并首先从 SQL 代理更新该表,然后在该表上使用索引键并将该索引用作FactStoreSale表中的 ProductKeyInt(例如 ProductKeyInt 将是某种子查询FactStoreSale获取与ToDateProductKey对应的DimProduct中最大的值。

有没有人有任何意见?有没有更简单的方法?我不想将字符串作为 JOIN 键,因为例如增加了 CPU 时间

Sol*_*zky 6

  1. 你并不需要使用ProductKey中键列DimProduct。您可以创建一个代理键,它是一个复合键,由DimProductIDIDENTITY列和 SCD 的每一行递增,以及ProductID每个ProductKey. 无论是INT(最有可能的,除非你将永远不会有非常多的独特的产品,在这种情况下,我可能会选择SMALLINTProductID它给你65K值使用)。

    这种方法使您既能够引用产品的任何特定版本(使用IDENTITY列,或者两者都可以更好地使用索引),并且能够仅使用非列来聚合特定产品的所有版本-IDENTITY列。

    在任何一种情况下,您通常都不需要对ProductKey列/值进行 JOINing 。

  2. 当你确实需要过滤器或连接上ProductKey,假设有大写和小写字母之间没有功能上的差异,你应该强制所有以大写使用二进制排序规则(任意整理的结束_BIN2,不是_BIN,虽然最有可能Latin1_General_100_BIN2)。大多数人不认为将排序规则用于包含字母数字代码的字符串列,这些列在任何情况下都没有大小写(或假名或宽度或重音不敏感)的目的,也没有用于评估复杂的语言规则,例如哪些字符序列等同于其他语言中的其他字符。非二进制排序规则有很多它们应用的复杂规则,而这些规则需要时间。使用二进制排序规则将是很多 更快,因为它只是比较字节,这就是为什么你需要强制大写以防有人输入小写字母字符。

    因此,为此,请确保Latin1_General_100_BIN2在创建表时设置要使用的列的排序规则。如果已经创建了表,请使用ALTER TABLE ... ALTER COLUMN设置排序规则,以便默认使用。