在一定条件下,建立两个数据表中的一个


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

合并的dataTable如下所示:

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表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还要为其添加一个Column (这也添加了零(0),我不需要在Column中添加它们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名称可以包含两个以上的重复项吗?例如,宝马是否可以存在三个重复项?2.我们如何定义保留哪些重复记录以及删除哪些记录?例如,我们可以保留最少的记录NRO并删除其他记录。
Iliar Turdushev

@IliarTurdushev 1.数据表中不能包含两个以上的“重复项” NAME。如果超过两个-错误(错误处理程序)。2.我的示例中有一个错误,我已经解决了。感谢您提及这一点,这一点很重要。
Hatman

您可以共享queryStringFI和/或queryStringSE的值吗?再加上您正在使用哪个数据库?
ATTA

@ATTA我无法提供对实际数据库的访问。你是说数据库类型?正如其所读
-ODBC

实际上,我喜欢看查询是通过哪个数据来获取数据的,但是基于我写过《答案》的一些假设。请查看并提供您的反馈。谢谢
ATTA

Answers:


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

我不确定在tResult.Select上foreach的性能,对于较大的数据表,最终结果可能很慢(假设tResult.Select为O(n),那么对于foreach它将导致O(n ^ 2)执行时间)
CitrusO2

2

尝试这个:

  1. 在针对表1和表2的两个查询中均包含NRO1字段
  2. 为表1设置NRO1的默认值0(修改queryStringSE)

    例如:SELECT NRO,0 AS NRO1,NAME,NAMEA,NAMEB,... FROM TABLE1

  3. 为表2设置NRO的默认值0(修改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. 检查数据表“结果”以获取所需值

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();
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.