2

すべてのテーブルには100を超える列があります-1つは650です。データベースは非常に非正規化されており、同じデータが同じ行のいくつかの列で表現されることが多いことがわかりました。

たとえば、テーブルの 1 つの列のサンプルを次に示します。

[MEMBERADDRESS] [varchar](331) NULL,
[DISPLAYADDRESS] [varchar](max) NULL,

[MEMBERINLINEADDRESS] [varchar](max) NULL,
[DISPLAYINLINEADDRESS] [varchar](250) NULL,

[__HISTISDN] [varchar](25) NULL,
[HISTISDN] [varchar](25) NULL,
[MYDIRECTISDN] [varchar](25) NULL,
[MYISDN] [varchar](25) NULL,

[__HISTALT_PHONE] [varchar](25) NULL,
[HISTALT_PHONE] [varchar](25) NULL,

MEMBERADDRESSテーブル内のすべての行でとDISPLAYADDRESSが同じ値であることがわかります。ここで示したフィールドの他のクラスターについても同じことが言えます。

このようなすべてのケースを手動で特定することは非常に難しく、時間がかかります。テーブルのすべての行で 2 つのフィールドの値が同じかどうかを識別するクエリを作成することはできますか?

そうでない場合、この種の問題を特定するのに役立つ既存のツールはありますか?

4

2 に答える 2

2

このクエリを単純化するには、次の 2 つの方法があります。

  • クエリを生成するスクリプトを作成します。スクリプトにテーブルの名前と疑わしい列を入力し、列の各ペアが等しいかどうかをチェックするクエリを生成させます。これは、あなたのような 1 回限りの状況で実装する最速のアプローチです。
  • データを「正規化」するクエリを作成し、それに対して検索します。クエリをそれ自体に自己結合してから、重複を除外します。

2 番目のアプローチの簡単な説明を次に示します。

SELECT id, name, val FROM (
    SELECT id, MEMBERADDRESS as val,'MEMBERADDRESS' as name FROM MyTable
    UNION ALL
    SELECT id, DISPLAYADDRESS as val,'DISPLAYADDRESS' as name FROM MyTable
    UNION ALL
    SELECT id, MEMBERINLINEADDRESS as val,'MEMBERINLINEADDRESS' as name FROM MyTable
    UNION ALL
    ...
) first
JOIN (
    SELECT id, MEMBERADDRESS as val,'MEMBERADDRESS' as name FROM MyTable
    UNION ALL
    SELECT id, DISPLAYADDRESS as val,'DISPLAYADDRESS' as name FROM MyTable
    UNION ALL
    SELECT id, MEMBERINLINEADDRESS as val,'MEMBERINLINEADDRESS' as name FROM MyTable
    UNION ALL
    ...
) second ON first.id=second.id AND first.value=second.value

100 列の場合、多くの手作業があります (少なくともN^2、最初のアプローチのように大きくはなりませんが、それでも多くの手動入力が必要です)。UNION ALL小さなスクリプトを使用して接続された選択を生成する方がよい場合があります。

于 2013-03-27T17:24:20.500 に答える
1

次のアプローチではunpivot、トリプルを作成するために使用します。いくつかの仮定があります。値は null ではありません。各行には ID があります。および列には互換性のある型があります。

select t.which, t2.which 
from (select id, which, value
      from MEMBERADDRESS
      unpivot (value for which in (<list of columns here>)) up
     ) t full outer join
     (select id, which, value
      from MEMBERADDRESS
      unpivot (value for which in (<list of columns here>)) up
     ) t2
     on t.id = t2.id and t.which <> t2.which
group by t.which, t2.which
having sum(case when t.value = t2.value then 1 else 0 end) = count(*)

これは、id、どの列、その列の値の 3 つの列を持つ新しいテーブルを作成することによって機能します。次に、id (比較を 1 つの行内に保持するため) と値 (一致する値を取得するため) に対して自己結合を行います。クエリの 2 つの半分で列が同じであるため、この自己結合は常に一致する必要があります。

次にhaving、指定された列のペアの両側で同じ値の数をカウントします。これらがすべて同じ場合、マッチングは成功です。

having句を省略して、次のようなものを使用することもできます。

select t.which, t2.which, sum(case when t.value = t2.value then 1 else 0 end) as Nummatchs,
       count(*) as NumRows

より完全な情報を得るために。

于 2013-03-27T17:32:35.587 に答える