2

3 つの列を持つ SQL Server テーブルがあります。

表1

col1 int
col2 int
col3 string

3 つの列すべてに一意の制約が定義されています(col1, col2, col3)

ここで、このテーブルにレコードを追加したい .csv ファイルがあり、*.csv ファイルには重複したレコードが含まれている可能性があります。

上記のシナリオで重複を回避するためのさまざまなオプションを検索しました。以下は、私にとってうまく機能している3つのオプションです。最適な方法を選択できるように、各方法の長所と短所についていくつかのアイデアを検討してください。

オプション1 :

最初に重複を回避します。つまり、csv ファイルからリストにオブジェクトを追加します。私はHashSet<T>これに使用し、以下のタイプ T のメソッドをオーバーライドしました。

public override int GetHashCode()
{
    return col1.GetHashCode() + col2.GetHashCode() + col3.GetHashCode();
}

public override bool Equals(object obj)
{
    var other = obj as T;
    if (other == null)
    {
        return false;
    }
    return col1 == other.col1
        && col2 == other.col2
        && col3 == other.col3;
}

オプション #2

List<T>の代わりに持つHashSet<T>

すべてのオブジェクトが追加された後に重複を削除するList<T>

    List<T> distinctObjects = allObjects
        .GroupBy(x => new {x.col1, x.col2, x.col3})
        .Select(x => x.First()).ToList();

オプション #3

すべてのオブジェクトが に追加された後、重複を削除しDataTableます。

public static DataTable RemoveDuplicatesRows(DataTable dataTable)
{
    IEnumerable<DataRow> uniqueRows = dataTable.AsEnumerable().Distinct(DataRowComparer.Default);
    DataTable dataTable2 = uniqueRows.CopyToDataTable();
    return dataTable2;
}

実行時間を比較したことはありませんが、最初のステップとして重複を削除するため、オプション 1 を好みます。したがって、必要なものだけを先に進めます。

私が最良のものを選ぶことができるように、あなたの意見を共有してください.

どうもありがとう!

4

2 に答える 2

5

オプション 1 が気に入っていますHashSet<T>。これは、DB に送信する前に重複を回避する迅速な方法を提供します。たとえば、オーバーライドされた System.Object.GetHashCode に最適なアルゴリズムは何ですか?GetHashCodeの Skeet の実装を使用して、より良い を実装する必要があります。

ただし、問題があります。CSV の複製となる可能性のあるデータがテーブルに既に含まれている場合はどうなるでしょうか。簡単HashSetに実際に機能させるには、最初にテーブル全体をコピーする必要があります。あなたはそれを行うことができますが、これを解決するために、オプション1を一時テーブルとSkip-over/ignore duplicate rows on insertのような挿入ステートメントと組み合わせることができます:

INSERT dbo.Table1(col1, col2, col3)
SELECT col1, col2, col3 
FROM dbo.tmp_holding_Table1 AS t
WHERE NOT EXISTS (SELECT 1 FROM dbo.Table1 AS d
WHERE col1 = t.col1
AND col2 = t.col2
AND col3 = t.col3);

この組み合わせにより、DB との間で転送されるデータの量が最小限に抑えられます。

于 2013-10-28T18:05:22.190 に答える
0

別の解決策はIGNORE_DUP_KEY = { ON | OFF }、インデックスを作成/再構築するときのオプションです。この解決策により、重複行の挿入でエラーが発生するのを防ぐことができます。代わりに、SQL Server は警告を生成します: Duplicate key was ignored..

CREATE TABLE dbo.MyTable (Col1 INT, Col2 INT, Col3 INT);
GO

CREATE UNIQUE INDEX IUN_MyTable_Col1_Col2_Col3 
ON dbo.MyTable (Col1,Col2,Col3)
WITH (IGNORE_DUP_KEY = ON);
GO

INSERT dbo.MyTable (Col1,Col2,Col3)
VALUES (1,11,111);
INSERT dbo.MyTable (Col1,Col2,Col3)
SELECT 1,11,111 UNION ALL 
SELECT 2,22,222 UNION ALL 
SELECT 3,33,333;
INSERT dbo.MyTable (Col1,Col2,Col3)
SELECT 2,22,222 UNION ALL 
SELECT 3,33,333;
GO
/*
(1 row(s) affected)

(2 row(s) affected)
Duplicate key was ignored.
*/


SELECT * FROM dbo.MyTable;
/*
Col1        Col2        Col3
----------- ----------- -----------
1           11          111
2           22          222
3           33          333
*/

注: ALTER INDEX でインデックス オプションを変更しようとすると、UNIQUE 制約があるため

ALTER INDEX IUN_MyTable_Col1_Col2_Col3
ON dbo.MyTable 
REBUILD WITH (IGNORE_DUP_KEY = ON)

次のエラーが表示されます。

Msg 1979, Level 16, State 1, Line 1
Cannot use index option ignore_dup_key to alter index 'IUN_MyTable_Col1_Col2_Col3' as it enforces a primary or unique constraint.`

したがって、このソリューションを選択した場合のオプションは次のとおりです。

1) 別の UNIQUE インデックスを作成し、UNIQUE 制約を削除します (このオプションはより多くのストレージ領域を必要としますが、常にアクティブな UNIQUE インデックス/制約になります) または

2) UNIQUE 制約を削除し、オプションを指定して UNIQUE インデックスを作成しWITH (IGNORE_DUP_KEY = ON)ます (この最後のオプションはお勧めしません)。

于 2013-10-28T19:25:00.670 に答える