Xây dựng một trong hai dữ liệu với các điều kiện nhất định


13

Đầu tiên tôi cần lấy tất cả dữ liệu từ ODBC (cái này đã hoạt động rồi).

Sau đó đến phần phức tạp nhất mà tôi không chắc làm thế nào nó có thể được thực hiện. Có hai bảng dữ liệu trong ODBC. Tôi đang hợp nhất chúng với mã hiện tại của tôi và lọc chúng với các tham số nhất định.

Bảng 1 trong cơ sở dữ liệu:

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 

Bảng 2 trong cơ sở dữ liệu:

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

Dữ liệu đã hợp nhất trông như thế này:

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 

Tuy nhiên, dữ liệu đầu ra được hợp nhất sẽ trông như thế này (để có khả năng làm việc với nó hơn nữa):

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 

Tìm bản sao trong NAME. Chỉ để lại một trong số họ, gán một số từ Bảng 1 đến NROtừ Bảng 2 đến NRO1. Số bảng 1 phải ở trong NRO, số 2 bảng nên ở NRO1.

Sau khi kết nối với ODBC, tôi điền vào một bảng với dữ liệu từ Bảng 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);

        }

sau đó tôi nhận dữ liệu từ Bảng 2 khác và hợp nhất chúng bằng cách:

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

Sau đó tôi đang thực hiện lọc (tôi cần có các hàng chỉ bắt đầu bằng 4 và 1 NRO, cũng có các hàng có số bắt đầu khác):

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

Sau đó, tôi sẽ thêm một Cột nữa cho NRO1(đây cũng là thêm số không (0) Tôi không cần chúng trong Cột 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
        }

Tôi có thể bắt các bản sao với mã này

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

Nhưng làm thế nào để thực hiện phần còn lại? Điều này nên được thực hiện bởi một vòng lặp với việc xây dựng một bảng mới? Làm thế nào tôi có thể thực hiện tham gia và loại bỏ trùng lặp dataTable?


1. Có thể dataTablechứa nhiều hơn hai bản sao cho một số tên? Ví dụ, có thể tồn tại ba bản sao cho BMW không? 2. Làm thế nào chúng ta có thể xác định bản ghi song công nào cần lưu giữ và bản ghi nào cần xóa? Ví dụ: chúng ta có thể giữ bản ghi với mức tối thiểu NROvà xóa bản ghi khác.
Iliar Turdushev

@IliarTurdushev 1. dữ liệu không thể chứa nhiều hơn một "bản sao" trong NAME. Nếu có nhiều hơn hai - lỗi (xử lý lỗi). 2. Có một lỗi trong ví dụ của tôi, tôi đã sửa nó ngay bây giờ. Cảm ơn bạn đã đề cập đến điều này, nó rất quan trọng.
hatman

Bạn có thể vui lòng chia sẻ các giá trị của queryStringFI và / hoặc queryStringSE không? Cộng với DB nào bạn đang sử dụng?
ATTA

@ATTA Tôi không thể cung cấp quyền truy cập vào cơ sở dữ liệu thực tế. Ý bạn là loại DB? Khi nó đọc trong câu hỏi - ODBC
hatman

Trên thực tế, tôi thích xem truy vấn mà dữ liệu đang được tìm nạp, tuy nhiên, dựa trên một số giả định tôi đã viết Trả lời. Vui lòng xem lại và đưa ra phản hồi của bạn. Cảm ơn
ATTA

Câu trả lời:


3

Bạn có thể thay thế merge()cuộc gọi bằng một phương thức tùy chỉnh, thực hiện việc hợp nhất và lọc cùng một lúc. Xem ví dụ dưới đây. Tôi nghĩ rằng đây là một cách tiếp cận tốt hơn so với việc hợp nhất đầu tiên (giới thiệu các hàng trùng lặp trong bảng kết quả) và sau đó lọc (nghĩa là loại bỏ các hàng trùng lặp).

Ở đây, người ta cho rằng tất cả các tham số có cùng định dạng. Các tTempbảng được sử dụng như một lưu trữ tạm thời về nội dung của bảng t2nhưng với cột phụ. Điều này cho phép nhập các hàng trong bảng kết quả.

Có thể có một giải pháp thanh lịch hơn, nhưng điều này nên hoạt động như dự định. Xin lưu ý rằng tôi đã bỏ qua yêu cầu bổ sung của bạn về các giá trị được phép NRO, mà tôi chắc chắn rằng bạn có thể dễ dàng thêm vào.

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

Cảm ơn vì điều này! Tôi đoán tôi đã làm điều gì đó sai khi tôi nhận được '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?)sau khi thay thế dataTable.Merge(newTable);bởidataTable.Merge_it(newTable);
hatman

Bạn có thể đặt mã trong một lớp mới. Chỉ cần đặt class Merger {...}xung quanh mã của tôi và gọi Merger.merge_it(...). Bạn phải chuẩn bị các thông số đầu vào, mặc dù.
lzydrmr

... Và bạn phải thêm các usingchỉ thị còn thiếu , tất nhiên. Nó chỉ là một đoạn trích (từ một chương trình làm việc).
lzydrmr

Tôi không chắc chắn về hiệu suất của foreach trên tResult.Select, có thể kết thúc rất chậm đối với các cơ sở dữ liệu lớn hơn (giả sử tResult. Chọn là O (n), sau đó với foreach nó sẽ dẫn đến O (n ^ 2) thời gian thực hiện)
CitrusO2

2

Thử cái này:

  1. Bao gồm trường NRO1 trong cả hai truy vấn cho Bảng1 và Bảng2
  2. Đặt giá trị mặc định 0 của NRO1 cho Bảng1 (sửa đổi queryStringSE)

    ví dụ: CHỌN NRO, 0 NHƯ NRO1, NAME, NAMEA, NAMEB, ... TỪ BẢNG1

  3. Đặt giá trị mặc định 0 của NRO cho Bảng2 (sửa đổi queryStringFI)

    ví dụ: CHỌN 0 NHƯ NRO, NRO NHƯ NRO1, NAME, NAMEA, NAMEB, ...... TỪ BẢNG2

Bảng 1 sẽ giống như:

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

Bảng 2 sẽ giống như:

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. Hợp nhất các bảng như bạn đã làm

Thêm các dòng mã sau:

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. Kiểm tra "kết quả" DataTable cho các giá trị mong muốn

0

bạn có thể giữ cùng một tên cột trong cả hai bảng nếu chúng biểu thị cùng một loại thực thể thì hãy xem mã này

 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();
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.