2009-08-04 14 views
1

dire que j'ai un DataTable dans ce format:LINQ se joindre, le regroupement, avec roll-up parent

id | key1 | key2 | data1 | data2 | parentID 
10 | AA | one | 10.3 | 0.3 | -1 
10 | AA | two | 20.1 | 16.2 | -1 
10 | BB | one | -5.9 | 30.1 | -1 
20 | AA | one | 403.1 | -20.4 | 10 
30 | AA | one | 121.5 | 210.3 | -1 

et un second DataTable comme ceci:

id | data 
10 | 5500 
20 | -3000 
30 | 500 

ce que je veux faire est agrégé les données au niveau "id", avec le champ "data" de la deuxième table ajouté au "data1" du premier réseau, et "data2" juste résumé par lui-même. J'ai trouvé comment faire ceci, mais ce que je suis coincé à ceci est ceci: Je veux des données pour n'importe quoi avec "parentID"! = -1 à être ajouté à son parent. donc la sortie des données ci-dessus devrait être

id | data1 | data2 
10 | 2927.6 | 26.2 
30 | 621.5 | 210.3 

Y at-il un moyen efficace de le faire?

modifier: exemple de code

 DataTable dt1 = new DataTable(); 
     dt1.Columns.Add("id", typeof(int)); 
     dt1.Columns.Add("key1", typeof(string)); 
     dt1.Columns.Add("key2", typeof(string)); 
     dt1.Columns.Add("data1", typeof(double)); 
     dt1.Columns.Add("data2", typeof(double)); 
     dt1.Columns.Add("parentID", typeof(int)); 

     DataTable dt2 = new DataTable(); 
     dt2.Columns.Add("id", typeof(int)); 
     dt2.Columns.Add("data", typeof(double)); 

     dt1.Rows.Add(new object[] { 10, "AA", "one", 10.3, 0.3, -1 }); 
     dt1.Rows.Add(new object[] { 10, "AA", "two", 20.1, 16.2, -1 }); 
     dt1.Rows.Add(new object[] { 10, "BB", "one", -5.9, 30.1, -1 }); 
     dt1.Rows.Add(new object[] { 20, "AA", "one", 403.1, -20.4, 10 }); 
     dt1.Rows.Add(new object[] { 30, "AA", "one", 121.5, 210.3, -1 }); 

     dt2.Rows.Add(new object[] { 10, 5500 }); 
     dt2.Rows.Add(new object[] { 20, -3000 }); 
     dt2.Rows.Add(new object[] { 30, 500 }); 

     var groups = dt1.AsEnumerable() 
         .GroupBy(e => e["id"]) 
         .Select(e => new 
            { 
             id = e.Key, 
             net_data1 = e.Sum(w => (double)w["data1"]), 
             net_data2 = e.Sum(w => (double)w["data2"]) 
            }) 
         .GroupJoin(dt2.AsEnumerable(), e1 => e1.id, e2 => e2["id"], 
            (a1, a2) => new 
               { 
                id = a1.id, 
                net_data1 = a1.net_data1 + a2.Sum(w => (double)w["data"]), 
                net_data2 = a1.net_data2 
               }); 
+1

Pourquoi ne pas afficher le code que vous avez déjà ... –

Répondre

0

Malheureusement, SQL (et, par extension, LINQ) n'est pas bien adapté à la récursivité. La colonne parentID peut-elle avoir plusieurs niveaux de profondeur? Comme ceci:

ID  Parent 
------------------ 
10  -1 
20  10 
30  10 
40  20 

Si vous voulez revenir sur les étapes à partir ID 40 à 10 ID, vous devez abandonner une approche SQL/LINQ et juste le faire dans le code.

+0

Nope, dans ce cas, il est juste un niveau. – toasteroven

0

Cela ressemble à une bonne utilisation d'une jointure de groupe. Quelque chose comme cela pourrait fonctionner (même si elle est complètement non testé):

var items = from parent in context.dataTable 
      join child in context.dataTable on parent.id equals child.parentID into children 
      where parent.parentID == -1 
      select new { id = parent.id, 
         data1 = (parent.data1 + children.Sum(c => c.data1)), 
         data2 = (parent.data2 + children.Sum(c => c.data2)) }; 
+0

Je pense que je vois la logique derrière ce que vous allez, je vais l'essayer. sur une note de côté, une façon dont j'ai réussi à obtenir ce que je veux est d'ajouter la même colonne "parentID" à la deuxième DataTable, et de grouper par et rejoindre sur "parentID" si "id"! = -1 ... pas aussi élégant que je le voudrais, mais ça marche. – toasteroven