Belirli koşullarla ikisinden bir datatable oluşturun


13

Öncelikle ODBC'den tüm verileri almam gerekiyor (bu zaten çalışıyor).

Daha sonra nasıl yapılabileceğinden emin olmadığım en karmaşık kısım geliyor. ODBC'de iki veri tablosu vardır. Onları mevcut kodumla birleştiriyorum ve belirli parametrelerle filtreliyorum.

Veritabanındaki Tablo 1:

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 

Veritabanındaki Tablo 2:

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

Birleştirilmiş veriler Tablo şu şekilde görünür:

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 

Bununla birlikte, birleştirilmiş çıktı verileri

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 

İçindeki kopyaları bulun NAME. Bunlardan yalnızca birini bırakın, Tablo 1'den NROTablo 2'ye bir sayı atayın NRO1. Tablo 1 numaraları NRO, Tablo 2 numaraları olmalıdır NRO1.

ODBC'ye bağlandıktan sonra bir tabloyu Tablo 1'deki verilerle dolduruyorum

        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);

        }

sonra başka bir Tablo 2 veri alıyorum ve bunları birleştirerek:

         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);
          }

Bundan sonra filtreleme yapıyorum (sadece 4 ve 1 inç ile başlayan satırlara ihtiyacım NROvar, diğer başlangıç ​​numarasına sahip satırlar da var):

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

Sonra bir sütun daha ekliyorum NRO1(bu da sıfırlar ekliyor (0) Ben Sütun onlara ihtiyacım yok 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
        }

Bu kodla kopyaları yakalayabilirim

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

ama geri kalanı nasıl yapılır? Bu yeni bir tablo oluşturmak ile bir döngü tarafından yapılmalıdır? Kopyaları birleştirme ve kaldırma işlemini nasıl yapabilirim dataTable?


1. Bir dataTableisim için ikiden fazla kopya içerebilir mi? Örneğin, BMW için üç kopya var mı? 2. Çift kayıtların hangilerinin saklanacağını ve hangilerinin silineceğini nasıl tanımlayabiliriz? Örneğin, minimum kayıt tutabilir NROve diğer kaydı silebiliriz.
Iliar Turdushev

@IliarTurdushev 1. datatable, ikiden fazla "kopya" içeremez NAME. İkiden fazla hata varsa (hata işleyici). 2. Örneğimde bir hata oluştu, şimdi düzelttim. Bundan bahsettiğiniz için teşekkürler, önemli.
hatman

Lütfen queryStringFI ve / veya queryStringSE değerlerini paylaşabilir misiniz? Ayrıca hangi DB'yi kullanıyorsunuz?
ATTA

@ATTA Gerçek veritabanına erişim sağlayamıyorum. DB tipi mi demek istiyorsun? Söz konusu gibi - ODBC
hatman

Aslında ben cevap yazdım birkaç varsayımlara dayanarak, hangi veri getiriliyor sorgu görmek sevdim. Lütfen görüşlerinizi bildirin ve verin. Teşekkürler
ATTA

Yanıtlar:


3

merge()Aramayı, birleştirme ve filtrelemeyi aynı anda gerçekleştiren özel bir yöntemle değiştirebilirsiniz . Aşağıdaki örneğe bakın. Bu ilk birleştirme (sonuç tablosunda yinelenen satırlar tanıtılması) ve sonra filtreleme (yani yinelenen satırları kaldırma) daha iyi bir yaklaşım olduğunu düşünüyorum.

Burada parametrelerin hepsinin aynı formata sahip olduğu varsayılmaktadır. tTempTablo tablo içeriğinin için geçici depolama olarak kullanılır t2ama ekstra sütun ile. Bu, sonuç tablosundaki satırların içe aktarılmasına izin verir.

Belki daha zarif bir çözüm var, ama bu amaçlandığı gibi çalışmalı. NROKolayca ekleyebileceğinizden emin olduğum için izin verilen değerlerle ilgili ek gereksiniminizi bıraktığımı lütfen unutmayın .

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;
            }
        }
    }

Bunun için teşekkür ederim! Ben alıyorum ben bir şey yanlış yaptım sanırım '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?)değiştirdikten sonra dataTable.Merge(newTable);tarafındandataTable.Merge_it(newTable);
Hatman'ın

Kodu yeni bir sınıfa yerleştirebilirsiniz. Sadece class Merger {...}kodumu koy ve ara Merger.merge_it(...). Bununla birlikte, giriş parametrelerini hazırlamanız gerekir.
lzydrmr

... ve usingelbette eksik direktifleri de eklemelisiniz . Bu sadece bir parçacık (çalışan bir programdan).
lzydrmr

Daha büyük veri tabloları için çok yavaş olabilen (tResult.Select'in O (n) olduğunu varsayalım, o zaman foreach ile O (n ^ 2) yürütme süresi)
CitrusO2

2

Bunu dene:

  1. Tablo1 ve Tablo2 için her iki sorguya da NRO1 alanını dahil et
  2. Table1 için NRO1'in varsayılan değerini 0 olarak ayarlayın (queryStringSE öğesini değiştirin)

    örn .: NRO'YU SEÇ, NRO1 OLARAK, AD, NAMEA, NAMEB, ... TABLO1'DEN

  3. Table2 için NRO varsayılan değerini 0 olarak ayarlayın (queryStringFI'yi değiştirin)

    örneğin: NRO OLARAK 0, NRO1 OLARAK NRO, AD, NAMEA, NAMEB, ...... TABLO2'DEN SEÇİN

Table1 şöyle görünecektir:

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 şöyle görünecektir:

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. Tabloları zaten yaptığınız gibi birleştirin

Aşağıdaki kod satırlarını ekleyin:

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. İstenen değerler için DataTable "sonucunu" kontrol edin

0

aynı varlık türünü belirtiyorlarsa aynı sütun adını her iki tabloda da saklayabilir ve ardından bu kodu görürsünüz

 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();
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.