8

私はサイト全体をチェックしてネット上でグーグルで検索しましたが、この問題の簡単な解決策を見つけることができませんでした。

約20列と10K行のデータテーブルがあります。4つのキー列に基づいて、このデータテーブルの重複行を削除する必要があります。.Netにはこれを行う機能がありませんか?私が探しているものに最も近い関数はdatatable.DefaultView.ToTable(true、表示する列の配列)でしたが、この関数はすべての列で区別されます。

誰かがこれを手伝ってくれるといいですね。

編集:これについて明確になっていないことをお詫び申し上げます。このデータテーブルは、DBからではなくCSVファイルを読み取ることによって作成されています。したがって、SQLクエリを使用することはできません。

4

13 に答える 13

9

LinqtoDatasetsを使用できます。これを確認してください。このようなもの:

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

List<DataRow> rows = new List<DataRow>();

DataTable contact = ds.Tables["Contact"];

// Get 100 rows from the Contact table.
IEnumerable<DataRow> query = (from c in contact.AsEnumerable()
                              select c).Take(100);

DataTable contactsTableWith100Rows = query.CopyToDataTable();

// Add 100 rows to the list.
foreach (DataRow row in contactsTableWith100Rows.Rows)
    rows.Add(row);

// Create duplicate rows by adding the same 100 rows to the list.
foreach (DataRow row in contactsTableWith100Rows.Rows)
    rows.Add(row);

DataTable table =
    System.Data.DataTableExtensions.CopyToDataTable<DataRow>(rows);

// Find the unique contacts in the table.
IEnumerable<DataRow> uniqueContacts =
    table.AsEnumerable().Distinct(DataRowComparer.Default);

Console.WriteLine("Unique contacts:");
foreach (DataRow uniqueContact in uniqueContacts)
{
    Console.WriteLine(uniqueContact.Field<Int32>("ContactID"));
}
于 2008-12-04T11:19:23.393 に答える
8

重複する行を削除するにはどうすればよいですか?。(そこでクエリを調整して、4つの主要な列に結合します)

編集:新しい情報を使用して、IEqualityComparer <T>を実装し、データ行でDistinctを使用するのが最も簡単な方法だと思います。それ以外の場合、DataTable/DataRowの代わりにIEnumerable/IListを使用している場合は、いくつかのLINQ-to-objectskung-fuで確実に可能です。

編集:IEqualityComparerの例

public class MyRowComparer : IEqualityComparer<DataRow>
{

    public bool Equals(DataRow x, DataRow y)
    {
        return (x.Field<int>("ID") == y.Field<int>("ID")) &&
            string.Compare(x.Field<string>("Name"), y.Field<string>("Name"), true) == 0 &&
          ... // extend this to include all your 4 keys...
    }

    public int GetHashCode(DataRow obj)
    {
        return obj.Field<int>("ID").GetHashCode() ^ obj.Field<string>("Name").GetHashCode() etc.
    }
}

次のように使用できます。

var uniqueRows = myTable.AsEnumerable().Distinct(MyRowComparer);
于 2008-12-04T11:13:34.997 に答える
1

Linqにアクセスできる場合は、メモリ内コレクションで組み込みのグループ機能を使用して、重複する行を選択できるはずです。

例としてLinqGroupをGoogleで検索

于 2008-12-04T11:17:53.617 に答える
1

コードを使用してDatatableから重複を削除するには、これが最善の方法であるに違いないと思います。LinqmoreLinq

リンク

RemoveDuplicatesRecords(yourDataTable);


private DataTable RemoveDuplicatesRecords(DataTable dt)
{
    var UniqueRows = dt.AsEnumerable().Distinct(DataRowComparer.Default);
    DataTable dt2 = UniqueRows.CopyToDataTable();
    return dt2;
}

MoreLinq

// Distinctby  column name ID 
var valueDistinctByIdColumn = yourTable.AsEnumerable().DistinctBy(row => new { Id = row["Id"] });
DataTable dtDistinctByIdColumn = valueDistinctByIdColumn.CopyToDataTable();
 

注:moreLinqライブラリを追加する必要があります。

morelinq では、DistinctBy という関数を使用して、Distinct オブジェクトを検索するプロパティを指定できます。

于 2013-05-09T10:29:03.503 に答える
1

削除を完了するには、Table.AcceptChanges() を呼び出す必要があることに注意してください。それ以外の場合、削除された行は、RowState が Deleted に設定されたまま DataTable に存在します。また、削除後も Table.Rows.Count は変更されません。

于 2011-10-01T11:41:30.947 に答える
0

関数の代わりにクエリを使用します。

DELETE FROM table1 AS tb1 INNER JOIN 
(SELECT id, COUNT(id) AS cntr FROM table1 GROUP BY id) AS tb2
ON tb1.id = tb2.id WHERE tb2.cntr > 1
于 2008-12-04T11:11:30.647 に答える
0

Liggett78の答えははるかに優れています-特に。私のエラーがあったので!次のように修正...

DELETE TableWithDuplicates
    FROM TableWithDuplicates
        LEFT OUTER JOIN (
            SELECT PK_ID = Min(PK_ID), --Decide your method for deciding which rows to keep
                KeyColumn1,
                KeyColumn2,
                KeyColumn3,
                KeyColumn4
                FROM TableWithDuplicates
                GROUP BY KeyColumn1,
                    KeyColumn2,
                    KeyColumn3,
                    KeyColumn4
            ) AS RowsToKeep
            ON TableWithDuplicates.PK_ID = RowsToKeep.PK_ID
    WHERE RowsToKeep.PK_ID IS NULL
于 2008-12-04T11:22:37.460 に答える
0

bytes.comでこれを見つけました:

System.Data.OleDb名前空間のクラスでJET4.0OLE DBプロバイダーを使用して、コンマ区切りのテキストファイルにアクセスできます(DataSet / DataTableを使用)。

または、System.Data.Odbc名前空間のクラスでODBC用のMicrosoft Text Driverを使用して、ODBCドライバーを使用してファイルにアクセスすることもできます。

これにより、他の人が提案したように、SQLクエリを介してデータにアクセスできるようになります。

于 2008-12-04T11:23:35.680 に答える
0

「このデータテーブルは、DB からではなく、CSV ファイルを読み取って作成されています。」

したがって、データベースの 4 つの列に一意の制約を設定すると、設計の下で重複する挿入は行われません。これが発生したときに続行する代わりに失敗することを決定しない限り、これは CSV インポート スクリプトで確実に構成可能です。

于 2008-12-04T11:26:11.507 に答える
0

これを試して

dtInput が重複レコードを持つデータ テーブルであると考えてみましょう。

重複する行をフィルタリングする新しい DataTable dtFinal があります。

したがって、私のコードは次のようになります。

DataTable dtFinal = dtInput.DefaultView.ToTable(true, 
                           new string[ColumnCount] {"Col1Name","Col2Name","Col3Name",...,"ColnName"});
于 2011-12-16T07:47:52.090 に答える
0

これは非常に単純なコードであり、フィルタを実行するために linq も個々の列も必要としません。行の列のすべての値が null の場合、その列は削除されます。


    public DataSet duplicateRemoval(DataSet dSet) 
{
    bool flag;
    int ccount = dSet.Tables[0].Columns.Count;
    string[] colst = new string[ccount];
    int p = 0;

    DataSet dsTemp = new DataSet();
    DataTable Tables = new DataTable();
    dsTemp.Tables.Add(Tables);

    for (int i = 0; i < ccount; i++)
    {
        dsTemp.Tables[0].Columns.Add(dSet.Tables[0].Columns[i].ColumnName, System.Type.GetType("System.String"));
    }

    foreach (System.Data.DataRow row in dSet.Tables[0].Rows)
    {
        flag = false;
        p = 0;
        foreach (System.Data.DataColumn col in dSet.Tables[0].Columns)
        {
            colst[p++] = row[col].ToString();
            if (!string.IsNullOrEmpty(row[col].ToString()))
            {  //Display only if any of the data is present in column
                flag = true;
            }
        }
        if (flag == true)
        {
            DataRow myRow = dsTemp.Tables[0].NewRow();
            //Response.Write("<tr style=\"background:#d2d2d2;\">");
            for (int kk = 0; kk < ccount; kk++)
            {
                myRow[kk] = colst[kk];         

                // Response.Write("<td class=\"table-line\" bgcolor=\"#D2D2D2\">" + colst[kk] + "</td>");
            }
            dsTemp.Tables[0].Rows.Add(myRow);
        }
    } return dsTemp;
}

これは、Excel シートから null データを削除するためにも使用できます。

于 2010-05-27T09:31:09.693 に答える