สร้างหนึ่ง datatable จากสองด้วยเงื่อนไขบางอย่าง


13

ก่อนอื่นฉันต้องได้รับข้อมูลทั้งหมดจาก ODBC (นี่ใช้งานได้แล้ว)

จากนั้นส่วนที่ซับซ้อนที่สุดที่ฉันยังไม่แน่ใจยังสามารถทำได้ มีข้อมูลสองตารางใน ODBC ฉันกำลังรวมเข้ากับรหัสปัจจุบันของฉันและกรองด้วยพารามิเตอร์บางอย่าง

ตารางที่ 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 

ตารางที่ 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

ผสานข้อมูลมีลักษณะเช่นนี้:

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 

อย่างไรก็ตามเอาท์พุทที่ผสานข้อมูล dataTable ควรมีลักษณะดังนี้

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 

NAMEค้นหาที่ซ้ำกันใน ทิ้งไว้เพียงหนึ่งของพวกเขากำหนดตัวเลขจากตารางที่ 1 ไปNROจากตารางที่ NRO12 ตารางที่ 1 หมายเลขควรจะอยู่ในNROตารางที่ 2 NRO1หมายเลขควรจะอยู่ใน

หลังจากเชื่อมต่อกับ ODBC ฉันกำลังเติมตารางหนึ่งด้วยข้อมูลจากตารางที่ 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);

        }

จากนั้นฉันก็รับข้อมูลจากตารางที่ 2 และรวมเข้ากับ:

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

หลังจากนั้นฉันกำลังทำการกรอง (ฉันต้องมีแถวที่เริ่มต้นด้วย 4 และ 1 นิ้วNROเท่านั้นยังมีแถวที่มีหมายเลขเริ่มต้นอื่น ๆ อยู่ด้วย):

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

จากนั้นฉันกำลังเพิ่มคอลัมน์อีกหนึ่งคอลัมน์สำหรับNRO1(นี่คือการเพิ่มศูนย์ (0) ฉันไม่ต้องการพวกเขาในคอลัมน์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
        }

ฉันสามารถจับคู่ที่ซ้ำกันด้วยรหัสนี้

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

แต่วิธีการที่เหลือ? สิ่งนี้ควรดำเนินการโดยการวนซ้ำกับการสร้างตารางใหม่หรือไม่? ฉันจะทำการเข้าร่วมและลบรายการที่ซ้ำได้dataTableอย่างไร


1.สามารถdataTableมีมากกว่าสองรายการที่ซ้ำกันสำหรับชื่อบางอย่าง? ตัวอย่างเช่นเป็นไปได้หรือไม่ที่จะมี BMW ซ้ำสามรายการ 2.เราจะกำหนดเร็กคอร์ดที่ซ้ำกันที่จะเก็บและที่จะลบได้อย่างไร? ตัวอย่างเช่นเราสามารถเก็บบันทึกด้วยขั้นต่ำNROและลบบันทึกอื่น ๆ
Iliar Turdushev

@IliarTurdushev 1. DataTable ไม่สามารถมีมากกว่าหนึ่งกว่าสอง "ที่ซ้ำกัน" NAMEใน ถ้ามากกว่าสอง - ข้อผิดพลาด (ตัวจัดการข้อผิดพลาด) 2. มีข้อผิดพลาดในตัวอย่างของฉันฉันได้แก้ไขแล้ว ขอบคุณที่พูดถึงสิ่งนี้เป็นสิ่งสำคัญ
hatman

คุณสามารถแบ่งปันค่าของ queryStringFI และ / หรือ queryStringSE ได้ไหม คุณกำลังใช้ฐานข้อมูลใดอยู่
ATTA

@ATTA ฉันไม่สามารถให้การเข้าถึงฐานข้อมูลจริงได้ คุณหมายถึง DB type? ในขณะที่มันอ่านคำถาม - ODBC
hatman

ที่จริงฉันชอบดูข้อความที่ดึงข้อมูล แต่ตามสมมติฐานบางอย่างที่ฉันเขียนคำตอบ โปรดตรวจสอบและให้ข้อเสนอแนะของคุณ ขอบคุณ
ATTA

คำตอบ:


3

คุณสามารถแทนที่การmerge()โทรด้วยวิธีการที่กำหนดเองซึ่งทำการผสานและกรองข้อมูลในเวลาเดียวกัน ดูตัวอย่างด้านล่าง ฉันคิดว่านี่เป็นวิธีที่ดีกว่าการผสานครั้งแรก (แนะนำแถวที่ซ้ำกันในตารางผลลัพธ์) แล้วกรอง (เช่นลบแถวที่ซ้ำกัน)

ในที่นี้จะสันนิษฐานว่าพารามิเตอร์ทั้งหมดมีรูปแบบเดียวกัน tTempตารางจะใช้เป็นที่เก็บชั่วคราวสำหรับเนื้อหาของตารางt2แต่มีคอลัมน์พิเศษ อนุญาตให้นำเข้าแถวในตารางผลลัพธ์ได้

อาจจะมีวิธีแก้ปัญหาที่สง่างามกว่า แต่ก็ควรใช้งานได้ตามที่ตั้งใจไว้ โปรดทราบว่าฉันได้ยกเลิกข้อกำหนดเพิ่มเติมของคุณเกี่ยวกับค่าที่อนุญาตสำหรับNROซึ่งฉันมั่นใจว่าคุณสามารถเพิ่มได้อย่างง่ายดาย

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

ขอบคุณสำหรับสิ่งนี้! ฉันเดาว่าฉันทำสิ่งผิดปกติเมื่อฉันได้รับ'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?)หลังจากแทนที่dataTable.Merge(newTable);โดยdataTable.Merge_it(newTable);
แฮตแมน

คุณสามารถใส่รหัสในคลาสใหม่ เพียงแค่ใส่รอบรหัสและโทรของฉันclass Merger {...} Merger.merge_it(...)คุณต้องเตรียมพารามิเตอร์อินพุต
lzydrmr

... และคุณต้องเพิ่มusingคำสั่งที่หายไปแน่นอน มันเป็นเพียงตัวอย่าง (จากโปรแกรมทำงาน)
lzydrmr

ฉันไม่แน่ใจเกี่ยวกับประสิทธิภาพของ foreach ผ่าน tResult.Select ซึ่งอาจทำให้ช้าลงสำหรับดาต้าดาต้าที่ใหญ่กว่า (สมมติว่า tResult.Select คือ O (n) จากนั้น foreach จะส่งผลให้ O (n ^ 2) เวลาดำเนินการ)
CitrusO2

2

ลองสิ่งนี้:

  1. รวมฟิลด์ NRO1 ในทั้งคิวรีสำหรับ Table1 และ Table2
  2. ตั้งค่าเริ่มต้น 0 ของ NRO1 สำหรับ Table1 (แก้ไข queryStringSE)

    เช่น: SELECT NRO, 0 AS NRO1, NAME, NAMEA, NAMEB, ... จาก Table1

  3. ตั้งค่าเริ่มต้น 0 ของ NRO สำหรับ Table2 (แก้ไข queryStringFI)

    เช่น: SELECT 0 AS NRO, NRO AS NRO1, NAME, NAMEA, NAMEB, ...... จาก Table2

Table1 จะมีลักษณะดังนี้:

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 จะมีลักษณะดังนี้:

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. รวมตารางตามที่คุณกำลังทำอยู่

เพิ่มบรรทัดของรหัสต่อไปนี้:

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. ตรวจสอบ "ผลลัพธ์" DataTable สำหรับค่าที่ต้องการ

0

คุณสามารถคงชื่อคอลัมน์เดิมไว้ในทั้งสองตารางหากพวกเขาแสดงถึงเอนทิตีประเภทเดียวกันจากนั้นดูรหัสนี้

 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();
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.