Створіть одну з двох даних із певними умовами


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 

Однак об'єднані вихідні даніTable повинні виглядати так (щоб мати можливість працювати з ним далі):

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від таблиці 2 до NRO1. Цифри таблиці 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та видаляти інший запис.
Іліар Турдушев

@IliarTurdushev 1. Datatable не може містити більше ніж два "дублікати" в NAME. Якщо більше двох - помилка (обробник помилок). 2. У моєму прикладі сталася помилка, я її тепер виправив. Дякую, що згадуєте про це, важливо.
хатман

Чи можете ви поділитися значеннями queryStringFI та / або queryStringSE? Плюс, яку БД ви використовуєте?
ATTA

@ATTA Я не можу надати доступ до фактичної бази даних. Ви маєте на увазі тип БД? Як йдеться у питанні - ODBC
хатман

Насправді мені сподобалось бачити запит, за яким збираються дані, однак на основі кількох припущень я написав відповідь. Перегляньте та дайте свої відгуки. Спасибі
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, ... OF TABLE1

  3. Встановити значення за замовчуванням 0 NRO для Table2 (змінити queryStringFI)

    наприклад: SELECT 0 AS NRO, NRO AS NRO1, NAME, NAMEA, NAMEB, ...... OF TABLE2

Таблиця1 виглядатиме так:

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

Таблиця2 виглядатиме так:

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();
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.