0

化学アプリケーションに非常に長い自然キー (数百文字) があります。値に対して MD5 を使用して、ersatz 自然キーを作成できます。私が知りたいのは、次のことが可能かどうかです。子行の 2 つのセットを考えてみましょう。

       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

親1と親2が同じ子のセットを持っているかどうかを判断するために、md5値の各3行セットを「計算」し、計算された値を互いに比較することは可能ですか? 子は同じ「順序」ではありませんが、実際には「順序」はありません。これらの 3 つのタプルは、実際には単なる行の「バッグ」です。

親 1 と親 2 は、それぞれのバッグに同じものを持っていますか?

繰り返しになりますが、明確にするために、1 つのセットを別のセットと行ごとに比較する必要がないようにしたいと考えています。理想的には、に類似したものを見つけたいと思います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 が存在する場合、異なるものだけを考慮しますか? 次に、バッグ A = バッグ B の場合のみ、またはバッグ A がバッグ B のサブセットであり、その逆の場合にのみ、同等性を探していますか?

等式関係を考慮して、異なる MD5 のみを探すソリューションを提示しました。

例に示すように、子テーブルに集約された 2 つの親テーブルがあるとします。

--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 に答える