Crie uma tabela de dados em duas com determinadas condições

13

Em primeiro lugar, preciso obter todos os dados do ODBC (isso já está funcionando).

Depois vem a parte mais complicada que ainda não tenho certeza de como isso pode ser feito. Existem duas tabelas de dados no ODBC. Estou mesclando-os com o meu código atual e filtrando-os com certos parâmetros.

Tabela 1 no banco de dados:

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 

Tabela 2 no banco de dados:

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

A tabela de dados mesclada fica assim:

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 

No entanto, o dataTable de saída mesclado deve ter esta aparência (para ter a possibilidade de trabalhar com ele ainda mais):

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 

Encontre duplicatas em NAME. Deixe apenas um deles, atribua um número da Tabela 1 a NROda Tabela 2 a NRO1. Quadro 1 os números devem ser em NRO, Tabela 2 os números devem ser em NRO1.

Após conectar-me ao ODBC, estou preenchendo uma tabela com dados da Tabela 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);

        }

então estou obtendo dados de outra Tabela 2 e os mesclando por:

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

Depois disso, estou realizando a filtragem (preciso ter linhas iniciando apenas com 4 e 1 pol. NRO, Também há linhas com outro número inicial):

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

Então estou adicionando mais uma coluna para NRO1(isso também está adicionando zeros (0), não preciso deles na coluna 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
        }

Eu posso pegar duplicatas com este código

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

mas como fazer o resto? Isso deve ser realizado por um loop com a construção de uma nova tabela? Como posso realizar a junção e a remoção de duplicatas dataTable?

Chapeleiro
fonte
1. Pode dataTableconter mais de duas duplicatas para algum nome? Por exemplo, é possível existir três duplicatas para a BMW? 2. Como podemos definir quais registros duplicados manter e quais excluir? Por exemplo, podemos manter o registro com o mínimo NROe excluir o outro registro.
Iliar Turdushev 23/03
@IliarTurdushev 1. a tabela de dados não pode conter mais de um "dois" duplicados em NAME. Se mais de dois - erro (manipulador de erros). 2. Houve um erro no meu exemplo, eu o corrigi agora. Obrigado por mencionar este, é importante.
hatman 25/03
Você pode compartilhar valores de queryStringFI e / ou queryStringSE? Além disso, qual banco de dados você está usando?
ATTA 25/03
@ATTA Não posso fornecer acesso ao banco de dados real. Você quer dizer tipo de banco de dados? Como se lê em questão - ODBC
hatman 25/03
Na verdade, gostei de ver a consulta de quais dados estão sendo buscados, no entanto, com base em algumas suposições que escrevi Answer. Revise e envie seus comentários. Obrigado
ATTA 26/03

Respostas:

3

Você pode substituir a merge()chamada por um método personalizado, que faz a mesclagem e a filtragem ao mesmo tempo. Veja o exemplo abaixo. Eu acho que essa é uma abordagem melhor do que a primeira mesclagem (introdução de linhas duplicadas na tabela de resultados) e a filtragem (ou seja, remoção das linhas duplicadas).

Aqui, supõe-se que todos os parâmetros tenham o mesmo formato. A tTemptabela é usada como armazenamento temporário para o conteúdo da tabela, t2mas com a coluna extra. Isso permite importar as linhas na tabela de resultados.

Talvez exista uma solução mais elegante, mas isso deve funcionar como pretendido. Observe que deixei de lado sua exigência adicional em relação aos valores permitidos NRO, os quais tenho certeza de que você pode adicionar facilmente.

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;
            }
        }
    }
lzydrmr
fonte
Obrigado por isso! Eu acho que fiz algo errado como estou recebendo '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?)depois de substituir dataTable.Merge(newTable);pordataTable.Merge_it(newTable);
hatman 25/03
Você pode colocar o código em uma nova classe. Basta colocar class Merger {...}meu código e ligar Merger.merge_it(...). Você precisa preparar os parâmetros de entrada.
lzydrmr 25/03
... e você precisa adicionar as usingdiretivas ausentes , é claro. É apenas um trecho (de um programa de trabalho).
lzydrmr 25/03
Não tenho certeza sobre o desempenho do foreach sobre o tResult.Select, que pode acabar sendo muito lento para tabelas de dados maiores (supondo que tResult.Select seja O (n), então, com o foreach, resultará em O (n ^ 2) tempo de execução)
CitrusO2 31/03
2

Tente o seguinte:

  1. Incluir campo NRO1 em ambas as consultas para Tabela1 e Tabela2
  2. Defina o valor padrão 0 de NRO1 para Tabela1 (modifique queryStringSE)

    por exemplo: SELECT NRO, 0 AS NRO1, NAME, NAMEA, NAMEB, ... FROM TABLE1

  3. Defina o valor padrão 0 do NRO para a Tabela2 (modificar queryStringFI)

    por exemplo: SELECT 0 AS NRO, NRO AS NRO1, NAME, NAMEA, NAMEB, ...... DA TABELA2

A Tabela1 será semelhante a:

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

A Tabela2 será semelhante a:

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. Mesclar tabelas como você já está fazendo

Adicione as seguintes linhas de código:

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. Verifique DataTable "resultado" para os valores desejados
ATTA
fonte
0

você pode manter o mesmo nome da coluna nas duas tabelas se elas denotarem o mesmo tipo de entidade e, em seguida, ver este código

 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();
    }
}
Jin Thakur
fonte