0

我在化学应用中有一个很长的自然键(数百个字符)。我可以针对该值使用 MD5 来创建一个 ersatz 自然键。我想知道以下是否可行;考虑两组子行:

       ParentTable
       parent1
       parent2

       ChildTable
       parent1....md5 value a
       parent1....md5 value b
       parent1....md5 value c

       parent2....md5 value b
       parent2....md5 value c
       parent2....md5 value a

是否可以“计算”每组三行 md5 值并将计算值相互比较以确定 parent1 和 parent2 是否具有相同的子集?孩子们不在同一个“顺序”中,但在任何情况下实际上都没有“顺序”——这三个元组实际上只是一个“袋子”行。

所以问题可能是,parent1 和 parent2 在各自的包里有相同的东西吗?

再说一次,要明确一点,我希望避免将一组与另一组逐行进行比较。理想情况下,我想找到类似于select sum(md5) from ChildTable where parent=1.

编辑:子表上会有一个唯一索引,以防止相同的值在同一个父表中出现多次:create unique index UX_CHILDTABLE on ChildTable(parent, md5);

EDIT2:将包与包进行比较时的“相同”或“平等”将被定义为:它们包含相同的一组 MD5 值,即一个包中的每个项目在另一个包中都有其双胞胎。bag1 的所有实体都在 bag2 中,bag2 的所有实体都在 bag1 中。

4

1 回答 1

1

我对您的答案有一个潜在的解决方案,但这取决于一些澄清。由于我是新用户,我无法在评论中提问。您声明您有与每个父母相对应的行“袋”。据我了解,包可以有重复的项目。如果您的父母中存在重复的 MD5,您是否只想考虑不同的 MD5?其次,您是否仅在袋 A = 袋 B 时寻找相等性,或者当袋 A 是袋 B 的子集时,反之亦然?

我提出了一个解决方案,它只寻找考虑相等关系的不同 MD5:

假设我们有两个父表,它们聚合在一个子表中,如您的示例所示:

--Create tables that hold our data
if object_id('tempdb..#parent1') is not null drop table #parent1
create table #parent1 (parent varchar(20), words varchar(20), chem varchar(100), bHash varchar(34))
insert into #parent1 values ('parent 1', 'this', 'a', upper(sys.fn_sqlvarbasetostr(hashbytes('md5', 'a'))))
insert into #parent1 values ('parent 1', 'does', 'b', upper(sys.fn_sqlvarbasetostr(hashbytes('md5', 'b'))))
insert into #parent1 values ('parent 1', 'not', 'c', upper(sys.fn_sqlvarbasetostr(hashbytes('md5', 'c'))))

if object_id('tempdb..#parent2') is not null drop table #parent2
create table #parent2 (parent varchar(20), words varchar(20), chem varchar(100), bHash varchar(34))
insert into #parent2 values ('parent 2', 'matter', 'b', upper(sys.fn_sqlvarbasetostr(hashbytes('md5', 'b'))))
insert into #parent2 values ('parent 2', 'just', 'c', upper(sys.fn_sqlvarbasetostr(hashbytes('md5', 'c'))))
insert into #parent2 values ('parent 2', 'words', 'a', upper(sys.fn_sqlvarbasetostr(hashbytes('md5', 'a'))))
insert into #parent2 values ('parent 2', 'duplicate', 'a', upper(sys.fn_sqlvarbasetostr(hashbytes('md5', 'a'))))

if object_id('tempdb..#child') is not null drop table #child
select *
into #child
from #parent1
union all
select * from #parent2

通过将 MD5 值视为字符串,我们可以将 MD5 的行值连接成一个有序列表。连接后,我们可以生成一个新的 MD5 哈希,它适用于父级的唯一值集合。

if object_id('tempdb..#parentHash') is not null drop table #parentHash
select distinct parent
      --We can create a new hash off an ordered list of distinct values (this is the list)
      ,stuff((select ','+o.bHash
             from (select distinct parent, bHash from #child) o
             where o.parent = t.parent
             order by o.bHash
             for xml path('')),1,1,'') ordered_list
      --Create the hash
      ,upper(sys.fn_sqlvarbasetostr(hashbytes('md5',
           stuff((select ','+o.bHash
                 from (select distinct parent, bHash from #child) o
                 where o.parent = t.parent
                 order by o.bHash
                 for xml path('')),1,1,'')
       ))) parentHash
into #parentHash
from (select distinct parent, bHash from #child) t

然后,您可以查询父哈希值相等的这些值。

select distinct o.parent
      ,t.parent
from #parentHash o
inner join #parentHash t on o.parentHash = t.parentHash and o.parent <> t.parent

同样,此解决方案假定您只寻找具有相同唯一值的包。如果您担心作为彼此子集的重复项或父项,则必须探索不同的解决方案。

于 2013-10-09T23:51:39.763 回答