Construire un datatable sur deux avec certaines conditions

13

Tout d'abord, je dois obtenir toutes les données d'ODBC (cela fonctionne déjà).

Vient ensuite la partie la plus compliquée dont je ne sais pas encore comment cela peut être fait. Il y a deux tables de données dans ODBC. Je les fusionne avec mon code actuel et les filtre avec certains paramètres.

Tableau 1 dans la base de données:

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 

Tableau 2 dans la base de données:

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

La table de données fusionnée ressemble à ceci:

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 

Cependant, la table de données de sortie fusionnée devrait ressembler à ceci (pour avoir la possibilité de travailler avec elle plus loin):

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 

Trouvez des doublons dans NAME. Ne laissez qu'un seul d'entre eux, attribuez un numéro du tableau 1 au NROtableau 2 à NRO1. Les chiffres du tableau 1 doivent être en NRO, les chiffres du tableau 2 doivent être en NRO1.

Après la connexion à ODBC, je remplis un tableau avec les données du tableau 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);

        }

puis j'obtiens des données d'un autre tableau 2 et les fusionne en:

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

Après cela, j'effectue le filtrage (je dois avoir des lignes commençant uniquement par 4 et 1 NRO, il y a aussi des lignes avec un autre numéro de départ):

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

Ensuite, j'ajoute une autre colonne pour NRO1(cela ajoute également des zéros (0), je n'en ai pas besoin dans la colonne 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
        }

Je peux attraper des doublons avec ce code

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

mais comment faire le reste? Cela devrait être effectué par une boucle avec la construction d'une nouvelle table? Comment puis-je joindre et supprimer des doublons dataTable?

l'homme au chapeau
la source
1. Peut dataTablecontenir plus de deux doublons pour un nom? Par exemple, est-il possible d'exister trois doublons pour BMW? 2. Comment pouvons-nous définir lequel des enregistrements en double à conserver et lequel supprimer? Par exemple, nous pouvons conserver un enregistrement avec un minimum NROet supprimer l'autre enregistrement.
Iliar Turdushev
@IliarTurdushev 1. La table de données ne peut pas contenir plus d'un "deux doublons" dans NAME. Si plus de deux - erreur (gestionnaire d'erreurs). 2. Il y avait une erreur dans mon exemple, je l'ai corrigée maintenant. Merci d'avoir mentionné celui-ci, il est important.
Hatman
Pouvez-vous s'il vous plaît partager les valeurs de queryStringFI et / ou queryStringSE? De plus, quelle base de données utilisez-vous?
ATTA
@ATTA Je ne peux pas donner accès à la base de données réelle. Vous voulez dire le type DB? Comme il se lit en question - ODBC
hatman
En fait, j'ai aimé voir la requête par laquelle les données sont récupérées, cependant, sur la base de quelques hypothèses que j'ai écrites Answer. Veuillez réviser et donner votre avis. Merci
ATTA

Réponses:

3

Vous pouvez remplacer l' merge()appel par une méthode personnalisée, qui effectue la fusion et le filtrage en même temps. Voir l'exemple ci-dessous. Je pense que c'est une meilleure approche que la première fusion (introduction de lignes en double dans le tableau des résultats) puis le filtrage (c'est-à-dire la suppression des lignes en double).

Ici, on suppose que les paramètres ont tous le même format. La tTemptable est utilisée comme stockage temporaire pour le contenu de la table t2mais avec la colonne supplémentaire. Cela permet d'importer les lignes dans le tableau de résultats.

Il existe peut-être une solution plus élégante, mais cela devrait fonctionner comme prévu. Veuillez noter que j'ai omis votre exigence supplémentaire concernant les valeurs autorisées pour NRO, que je suis sûr que vous pouvez ajouter facilement.

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
la source
Merci pour ça! Je suppose que j'ai fait quelque chose de mal que je reçois '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?)après avoir remplacé dataTable.Merge(newTable);pardataTable.Merge_it(newTable);
hatman
Vous pouvez mettre le code dans une nouvelle classe. Mettez simplement class Merger {...}mon code et appelez Merger.merge_it(...). Vous devez cependant préparer les paramètres d'entrée.
lzydrmr
... et vous devez usingbien sûr ajouter les directives manquantes . C'est juste un extrait (d'un programme de travail).
lzydrmr
Je ne suis pas sûr de la performance de foreach sur le tResult.Select, qui pourrait finir par être très lent pour les plus grandes tables de données (en supposant que tResult.Select soit O (n), puis avec le foreach, il en résultera un O (n ^ 2) temps d'exécution)
CitrusO2
2

Essaye ça:

  1. Inclure le champ NRO1 dans les deux requêtes pour Table1 et Table2
  2. Définir la valeur par défaut 0 de NRO1 pour Table1 (modifier queryStringSE)

    par exemple: SELECT NRO, 0 AS NRO1, NAME, NAMEA, NAMEB, ... FROM TABLE1

  3. Définir la valeur par défaut 0 de NRO pour Table2 (modifier queryStringFI)

    Par exemple: SELECT 0 AS NRO, NRO AS NRO1, NAME, NAMEA, NAMEB, ...... FROM TABLE2

Le tableau 1 ressemblera à:

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

Le tableau 2 ressemblera à:

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. Fusionner des tables comme vous le faites déjà

Ajoutez les lignes de code suivantes:

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. Vérifiez le «résultat» de DataTable pour les valeurs souhaitées
ATTA
la source
0

vous pouvez conserver le même nom de colonne dans les deux tables si elles dénotent le même type d'entité alors voyez ce code

 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
la source