【问题标题】:Crafting a SP to determine which columns make a table unique制作一个 SP 以确定哪些列使表唯一
【发布时间】:2018-06-24 21:34:02
【问题描述】:

出于多种原因,您会想知道哪些列使表格独一无二。当您的表具有实际 PK 或只有几列时,这很容易做到。

但是,在这种情况下,我得到了很多没有指定任何数据类型的大表(50 多列),因此没有键。 有一些选项可以获取此信息;使用特定工具解析表或简单地询问表的所有者/创建者复合键是什么。 这可以证明是一个缓慢的过程。 我想看看我是否可以确定具有存储过程的表的复合键是什么。

我确定每张桌子都必须有一个。这是因为每个表中的每一行都是唯一的。

我在谷歌上花了一些时间在这件事上,但我只遇到了制作复合键等的方法。或者用复合键列出表的方法(仅当它们已经定义时)。

基本上我要创建的是一个 SP,它接受一个表名并返回我可以变成复合键的列。

谁能指出我正确的方向,因为我现在有点迷茫。 我在这个项目中使用的是 SQL Server 2014。

【问题讨论】:

  • 复合键是否定义了,还是需要从数据中算出来?因为如果它已定义,您只需要检查一些系统表,如 sys.indexes 和 sys.index_columns。如果您需要从数据中找出答案,您可能需要编写大量测试。您使用的是什么版本的 sql server?
  • key没有定义,需要自己从数据中找出来。这就是其中棘手的部分。目前我使用的是 SQL Server 2014。我也在寻找问题背后的逻辑。
  • 我的想法是对每个可能的列组合使用 count(distinct),直到找到结果为 count(*) 的组合。当然,手动执行此操作会非常慢,但可以使用动态 SQL 将其自动化,从 sys.columns 中的数据构建查询。我不知道这是否是最好的方法,但这是我现在唯一能想到的方法。我目前没有时间为此创建代码示例,所以我还没有将其作为答案发布。
  • 逻辑?取所有合适的列 ([[n]var]char(not max), int),取所有这些的全部或部分组合,选择记录数,按部分列集分组 - 如果记录数相同,你有唯一设置。
  • @ZoharPeled - 以问题中的示例为例。有 50 多列,并且可能需要 1 列和全部 50 列之间的任何位置来创建密钥。要测试的组合数量惊人(2^50)

标签: database tsql stored-procedures sql-server-2014 etl


【解决方案1】:

这不是存储过程最合适的任务,但随着时间的推移它是可行的。不幸的是,直接完整的解决方案需要相当多的时间,太多了,我想说。时间复杂度约为 O(2^C),其中 C 是列数,每次尝试也需要相当长的时间。

完整解决方案的总体思路是迭代列集,表列的每个可能组合(在集合内没有特定顺序)。然后我们检查集合的耦合,并从通过测试的列中获取最少列。

好消息,对可能的解决方案进行了快速测试。检查计数(不同)=计数(*)。如果可以的话,你至少可以用整个表作为一个位键...

坏消息,它并不能解决问题。

但我们可以贪婪。

计算每列的唯一值并按降序对列进行排序。如果有简单的 1 列 PK,它将在第一列。

现在我们按此顺序获取列并添加到列集。如果所选列 1..K 的唯一值的乘积小于 count(*),则您无法从中获取唯一索引 - 更进一步。

一旦我们计算了足够多的可能性,请尝试使用动态 SQL 检查 count(distinct) 以对这些列进行选择。如果还不够,再往前走。

一旦我们获得足够的列来涵盖唯一性,我们就差不多完成了。现在让我们尝试从这个集合中删除一些列。从 1 迭代到 K 并尝试列集 (1..I-1, I+1..K)。如果它仍然是唯一的,请从集合中删除此列并继续删除列。

在删除列后继续正确迭代有点棘手,但它是可行的。

一旦我们尝试删除覆盖集的所有列,我们就完成了。

这不是精确的算法,所以你必须手动检查它,但至少你会有一些东西开始,它具有 O(C*D) 时间复杂度,其中 C 是列数,D 是表中的数据量。

【讨论】:

  • 谢谢,我理解你的做法。今晚下班回来后,我会开始做饭。看看具体会产生什么影响。
  • 这是一个比我想象的更好的解决方案,但如果 Panagiotis Kanavos 的答案得到验证,最好使用它而不是自己滚动。 +1。
  • 我明天将尝试设置一个测试脚本,看看会有什么影响。昨晚我正在与试图使用内置数据分析器的 SSIS 神作斗争。
【解决方案2】:

这是 ETL 项目中的常见问题 - 您获得一个文件、表或其他数据源,并且必须猜测唯一列、大小、不同值、列之间的关系、可空性等。

SSIS 已经有一个Data Profiling Task 可以读取源(例如表)并执行许多此类检查。您需要的是Candidate Key Profile。这将检查哪些列组合可以用作键或什至 近似 键(即不是 100% 唯一的)。

此过程需要很长时间,因为该任务必须读取所有数据并检查所有列组合的唯一性。结果保存在一个文件中,可以在Data Profile Viewer 中打开进行分析。

您可以一次使用多个配置文件以节省时间,例如一次性收集大小、分布和候选键。

您还可以使用多个分析任务一次分析多个源/表,或将其放入一个循环容器中,以分析文件夹中的所有文件或列表中的所有表。

【讨论】:

  • 我昨晚试过了,我可以确认这确实有效,因为我设法从 XML 中提取数据以用于表创建。
  • 但是我不想使用 SISS 包的主要原因是这需要人工(或者现在有可能动态生成包吗?(上次我检查的是一对夫妇)几年前,找不到这样做的方法))
【解决方案3】:

我觉得你只需要一个算法。如果您没有 PK,则可以将列用作索引中使用的关键嫌疑人。 您必须确保您的复合键在表格中是唯一的,因此必须查询数据。 这是我的想法: 0.查询表的行数 1. 选择可疑的列作为唯一键 2. 对该列进行字典计数查询,例如前 1000 行 3.如果结果为1000,则数据是唯一的。在这种情况下,用更多的行重复查询,直到达到表的行数。如果最后一个查询的结果等于您找到可能唯一键的表的行数。 4. 如果结果低于 1000,则用另一个嫌疑人制作复合键来补充所选列。用这个键从第 2 步开始重复。

这可能是一项缓慢而乏味的工作,您应该考虑到即使这样,您也不能确定您找到了真正的唯一键,只是一个与现有数据唯一的键。

【讨论】:

  • 这应该是评论,而不是答案,因为它实际上回答了问题。 SO 是一个问答网站,其中的答案应该是答案,这将有助于将来遇到同样问题的其他人
猜你喜欢
  • 2012-07-11
  • 2012-10-06
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多