Bangun satu datatable dari dua dengan kondisi tertentu

13

Pertama saya harus mendapatkan semua data dari ODBC (ini sudah berfungsi).

Kemudian muncul bagian yang paling rumit yang saya belum yakin bagaimana hal itu bisa dilakukan. Ada dua tabel data di ODBC. Saya menggabungkannya dengan kode saya saat ini dan memfilternya dengan parameter tertentu.

Tabel 1 dalam database:

NRO   NAME   NAMEA   NAMEB   ADDRESS   POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   ID  ACTIVE
123   Fiat   Punto   500     J5        K4      O3      P4        O2         JT        1   1
133   Opel   Meriva  FTG     J5        K4      O3      P4        O2         JO        3   1
153   MB     E200    C25     JN        KI      OP      PY        OR         JD        5   1
183   BMW    E64     SE0     JR        KE      OT      PG        OL         J8        9   1
103   Audi   S6      700     JP        KU      OU      PN        OH         J6        11  1 

Tabel 2 dalam database:

NRO   NAME   NAMEA   NAMEB   ADDRESS   POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   ID  ACTIVE
423   Fiat   Punto   500     J5        K4      O3      P4        O2         JT        1   1
463   BMW    E64     SE0     JR        KE      OT      PG        OL         J8        9   1

DataTable gabungan terlihat seperti ini:

NRO   NAME   NAMEA   NAMEB   ADDRESS   POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   ID  ACTIVE
423   Fiat   Punto   500     J5        K4      O3      P4        O2         JT        1   1
463   BMW    E64     SE0     JR        KE      OT      PG        OL         J8        9   1
123   Fiat   Punto   500     J5        K4      O3      P4        O2         JT        1   1
133   Opel   Meriva  FTG     J5        K4      O3      P4        O2         JO        3   1
153   MB     E200    C25     JN        KI      OP      PY        OR         JD        5   1
183   BMW    E64     SE0     JR        KE      OT      PG        OL         J8        9   1
103   Audi   S6      700     JP        KU      OU      PN        OH         J6        11  1 

Namun data output gabungan digabung akan terlihat seperti ini (untuk memiliki kemungkinan untuk bekerja dengannya lebih lanjut):

NRO  NRO1   NAME   NAMEA   NAMEB   ADDRESS   POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   ID  ACTIVE
123  423    Fiat   Punto   500     J5        K4      O3      P4        O2         JT        1   1
133         Opel   Meriva  FTG     J5        K4      O3      P4        O2         JO        3   1
153         MB     E200    C25     JN        KI      OP      PY        OR         JD        5   1
183  463    BMW    E64     SE0     JR        KE      OT      PG        OL         J8        9   1
103         Audi   S6      700     JP        KU      OU      PN        OH         J6        11  1 

Temukan duplikat di NAME. Sisakan satu saja, tetapkan nomor dari Tabel 1 hingga NROdari Tabel 2 hingga NRO1. Tabel 1 angka harus dalam NRO, tabel 2 nomor harus dalam NRO1.

Setelah terhubung ke ODBC saya mengisi satu tabel dengan data dari Tabel 1

        DataTable dataTable = new DataTable("COMPANY");

        using (OdbcConnection dbConnectionSE = new OdbcConnection(connectionStringSE))
        {
            dbConnectionSE.Open();
            OdbcDataAdapter dadapterSE = new OdbcDataAdapter();
            dadapterSE.SelectCommand = new OdbcCommand(queryStringSE, dbConnectionSE);

            dadapterSE.Fill(dataTable);

        }

maka saya mendapatkan data dari Tabel 2 lain dan menggabungkannya dengan:

         using (OdbcConnection dbConnectionFI = new OdbcConnection(connectionStringFI))
         {
              dbConnectionFI.Open();
              OdbcDataAdapter dadapterFI = new OdbcDataAdapter();
              dadapterFI.SelectCommand = new OdbcCommand(queryStringFI, dbConnectionFI);

              var newTable = new DataTable("COMPANY");
              dadapterFI.Fill(newTable);

              dataTable.Merge(newTable);
          }

Setelah itu saya melakukan pemfilteran (saya harus memiliki baris yang hanya dimulai dengan 4 dan 1 NRO, ada juga baris dengan nomor awal lainnya):

DataTable results = dataTable.Select("ACTIVE = '1' AND (NRO Like '1%' OR NRO Like '4%')").CopyToDataTable();

Lalu saya menambahkan satu Kolom lagi untuk NRO1(ini juga menambahkan nol (0) Saya tidak membutuhkannya di Kolom NRO1):

        results.Columns.Add("NRO1", typeof(int)).SetOrdinal(1);

        foreach (DataRow row in results.Rows)
        {
            //need to set value to NewColumn column
            row["NRO1"] = 0;   // or set it to some other value
        }

Saya dapat menangkap duplikat dengan kode ini

var duplicates = results.AsEnumerable().GroupBy(r => r[2]).Where(gr => gr.Count() > 1);

tetapi bagaimana melakukan sisanya? Ini harus dilakukan oleh lingkaran dengan membangun tabel baru? Bagaimana saya dapat melakukan bergabung dan menghapus duplikat dataTable?

penjaga topi
sumber
1. Bisakah dataTableberisi lebih dari dua duplikat untuk beberapa nama? Misalnya, apakah mungkin ada tiga duplikat untuk BMW? 2. Bagaimana kita bisa menentukan catatan duplikat mana yang akan disimpan, dan mana yang akan dihapus? Misalnya, kita dapat menyimpan catatan dengan minimum NROdan menghapus catatan lainnya.
Iliar Turdushev
@IliarTurdushev 1. datatable tidak boleh mengandung lebih dari satu dari dua "duplikat" di NAME. Jika lebih dari dua - kesalahan (penangan kesalahan). 2. Ada kesalahan dalam contoh saya, saya telah memperbaikinya sekarang. Terima kasih telah menyebutkan yang ini, ini penting.
Hatman
Bisakah Anda berbagi nilai queryStringFI dan / atau queryStringSE? Ditambah DB mana yang Anda gunakan?
ATTA
@ATTA Saya tidak bisa menyediakan akses ke database aktual. Maksudmu tipe DB? Seperti yang terbaca dalam pertanyaan - ODBC
hatman
Sebenarnya saya suka melihat permintaan data yang diambil, namun, berdasarkan beberapa asumsi saya telah menulis Jawaban. Tinjau dan berikan tanggapan Anda. Terima kasih
ATTA

Jawaban:

3

Anda bisa mengganti merge()panggilan dengan metode kustom, yang melakukan penggabungan dan pemfilteran pada saat yang sama. Lihat contoh di bawah ini. Saya pikir ini adalah pendekatan yang lebih baik daripada penggabungan pertama (memperkenalkan baris duplikat di tabel hasil) dan kemudian menyaring (yaitu menghapus baris duplikat).

Di sini, diasumsikan bahwa semua parameter memiliki format yang sama. The tTemptable digunakan sebagai penyimpanan sementara untuk isi tabel t2tetapi dengan kolom tambahan. Ini memungkinkan mengimpor baris di tabel hasil.

Mungkin ada solusi yang lebih elegan, tetapi ini harus berfungsi sebagaimana dimaksud. Harap perhatikan bahwa saya telah mengabaikan persyaratan tambahan Anda mengenai nilai yang diizinkan untuk NRO, yang saya yakin dapat Anda tambahkan dengan mudah.

static void merge_it(DataTable t1, DataTable t2, DataTable tResult, DataTable tTemp)
    {
        tResult.Merge(t1);
        tResult.Columns.Add("NRO1", typeof(int));

        tTemp.Merge(t2);
        tTemp.Columns.Add("NRO1", typeof(int));

        foreach (DataRow row in tTemp.Rows)
        {
            string name1 = row.Field<string>("NAME");
            string name2 = row.Field<string>("NAMEA");
            DataRow[] matches = tResult.Select($"NAME = '{name1}' AND NAMEA = '{name2}'");
            if (matches.Length > 0)
            {
                matches[0].SetField<int>("NRO1", row.Field<int>("NRO"));
            }
            else
            {
                tResult.ImportRow(row);
            }
        }

        foreach (DataRow row in tResult.Rows)
        {
            if (row["NRO1"] == DBNull.Value)
            {
                row["NRO1"] = 0;
            }
        }
    }
lzydrmr
sumber
Terima kasih untuk ini! Saya kira saya melakukan sesuatu yang salah saat saya menerima 'DataTable' does not contain a definition for 'Merge_it' and no accessible extension method 'Merge_it' accepting a first argument of type 'DataTable' could be found (are you missing a using directive or an assembly reference?)setelah diganti dataTable.Merge(newTable);olehdataTable.Merge_it(newTable);
hatman
Anda bisa meletakkan kode di kelas baru. Letakkan saja class Merger {...}kode saya dan telepon Merger.merge_it(...). Anda harus menyiapkan parameter input.
lzydrmr
... dan Anda harus menambahkan usingarahan yang hilang , tentu saja. Itu hanya cuplikan (dari program kerja).
lzydrmr
Saya tidak yakin tentang kinerja pendahuluan atas tResult.Select, yang bisa berakhir sangat lambat untuk datatables yang lebih besar (dengan asumsi tResult.Select adalah O (n), maka dengan foreach itu akan menghasilkan O (n ^) 2) waktu eksekusi)
CitrusO2
2

Coba ini:

  1. Sertakan bidang NRO1 di kedua kueri untuk Table1 dan Table2
  2. Tetapkan nilai default 0 dari NRO1 untuk Table1 (ubah queryStringSE)

    mis: SELECT NRO, 0 AS NRO1, NAME, NAMEA, NAMEB, ... DARI TABLE1

  3. Tetapkan nilai default 0 dari NRO untuk Table2 (ubah queryStringFI)

    mis .: SELECT 0 AS NRO, NRO AS NRO1, NAME, NAMEA, NAMEB, ...... DARI TABLE2

Table1 akan terlihat seperti:

NRO  NRO1   NAME   NAMEA   NAMEB   ADDRESS   POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   ID  ACTIVE
123   0     Fiat   Punto   500     J5        K4      O3      P4        O2         JT        1   1
133   0     Opel   Meriva  FTG     J5        K4      O3      P4        O2         JO        3   1

Table2 akan terlihat seperti:

NRO  NRO1   NAME   NAMEA   NAMEB   ADDRESS   POSTA   POSTN   POSTADR   COMPANYN   COUNTRY   ID  ACTIVE
0    423    Fiat   Punto   500     J5        K4      O3      P4        O2         JT        1   1
0    463    BMW    E64     SE0     JR        KE      OT      PG        OL         J8        9   1
  1. Gabungkan tabel seperti yang sudah Anda lakukan

Tambahkan baris kode berikut:

var carGroups = dataTable.AsEnumerable().GroupBy(row => new 
{
   Name = row.Field<string>("Name"),
   NameA = row.Field<string>("NAMEA"),
   NameB = row.Field<string>("NAMEB")
   //Other fields.....
});

DataTable result = dataTable.Clone();

foreach(var grp in carGroups)            
    result.Rows.Add(grp.Sum(r1 => r1.Field<int>("NRO")), grp.Sum(r2 => r2.Field<int>("NRO1")), grp.Key.Name, grp.Key.NameA, grp.Key.NameB);              
  1. Periksa "hasil" DataTable untuk nilai yang diinginkan
ATTA
sumber
0

Anda bisa menyimpan nama kolom yang sama di kedua tabel jika mereka menunjukkan jenis entitas yang sama kemudian lihat kode ini

 private static void DemonstrateMergeTable()
{
    DataTable table1 = new DataTable("Items");

    // Add columns
    DataColumn idColumn = new DataColumn("id", typeof(System.Int32));
    DataColumn itemColumn = new DataColumn("item", typeof(System.Int32));
    table1.Columns.Add(idColumn);
    table1.Columns.Add(itemColumn);

    // Set the primary key column.
    table1.PrimaryKey = new DataColumn[] { idColumn };

    // Add RowChanged event handler for the table.
    table1.RowChanged += new 
        System.Data.DataRowChangeEventHandler(Row_Changed);

    // Add ten rows.
    DataRow row;
    for (int i = 0; i <= 9; i++)
    {
        row = table1.NewRow();
        row["id"] = i;
        row["item"] = i;
        table1.Rows.Add(row);
    }

    // Accept changes.
    table1.AcceptChanges();
    PrintValues(table1, "Original values");

    // Create a second DataTable identical to the first.
    DataTable table2 = table1.Clone();

    // Add column to the second column, so that the 
    // schemas no longer match.
    table2.Columns.Add("newColumn", typeof(System.String));

    // Add three rows. Note that the id column can't be the 
    // same as existing rows in the original table.
    row = table2.NewRow();
    row["id"] = 14;
    row["item"] = 774;
    row["newColumn"] = "new column 1";
    table2.Rows.Add(row);

    row = table2.NewRow();
    row["id"] = 12;
    row["item"] = 555;
    row["newColumn"] = "new column 2";
    table2.Rows.Add(row);

    row = table2.NewRow();
    row["id"] = 13;
    row["item"] = 665;
    row["newColumn"] = "new column 3";
    table2.Rows.Add(row);

    // Merge table2 into the table1.
    Console.WriteLine("Merging");
    table1.Merge(table2, false, MissingSchemaAction.Add);
    PrintValues(table1, "Merged With table1, schema added");
}

private static void Row_Changed(object sender, 
    DataRowChangeEventArgs e)
{
    Console.WriteLine("Row changed {0}\t{1}", e.Action, 
        e.Row.ItemArray[0]);
}

private static void PrintValues(DataTable table, string label)
{
    // Display the values in the supplied DataTable:
    Console.WriteLine(label);
    foreach (DataRow row in table.Rows)
    {
        foreach (DataColumn col in table.Columns)
        {
            Console.Write("\t " + row[col].ToString());
        }
        Console.WriteLine();
    }
}
Jin Thakur
sumber