2013-04-19 19 views
21

Chcę zrobić zapytanie z linq (lista obiektów) i naprawdę nie wiem jak to zrobić, mogę zrobić grupę i sumę, ale nie mogę wybrać reszty pola. Przykład:Wybrać wiele pól grupa według i suma

ID Value  Name Category 
1 5   Name1 Category1 
1 7   Name1 Category1 
2 1   Name2 Category2 
3 6   Name3 Category3 
3 2   Name3 Category3 

Chcę grupy przez ID, sum przez wartość i powrócić wszystkie pola jak ten.

ID Value  Name Category 
1 12  Name1 Category1 
2 1   Name2 Category2 
3 8   Name3 Category3 
+0

Czy masz czek? http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b i twoja sprawa: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – Aristos

+0

ponieważ wszystkie pola wydają się wyjątkowe każdy identyfikator, dlaczego nie uwzględnisz ich w grupie. – Habib

+0

Tak mogę zrobić, ale mam więcej pól niż ... :( – user2112420

Odpowiedz

44

Aktualizacja: Jeśli starasz się unikać grupowania dla wszystkich pól, można grupa po prostu przez Id:

data.GroupBy(d => d.Id) 
    .Select(
     g => new 
     { 
      Key = g.Key, 
      Value = g.Sum(s => s.Value), 
      Name = g.First().Name, 
      Category = g.First().Category 
     }); 

Ale ten kod zakłada, że ​​dla każdego Id obowiązują te same Name i Category. Jeśli tak, powinieneś rozważyć normalizację, jak sugeruje @Aron. Oznaczałoby to utrzymywanie Id i Value w jednej klasie i przenoszenie Name, Category (i jakiekolwiek inne pola byłyby takie same dla tego samego Id) do innej klasy, jednocześnie mając także Id jako odniesienie. Proces normalizacji zmniejsza redundancję i zależność danych.

+0

Tak, wiem to, ale po prostu nie chcę grupować wszystkich pól, byłby inny sposób, próbuję z first(), ale potem jak sumować? – user2112420

+0

Zaktualizowałem odpowiedź. –

+0

Tak, wiem co mówisz, mam normalizację DB, to tylko wynik mojego zapytania, ale dla każdego wiersza mojego zapytania powtarzam jego wartości i chcę je zgrupować i zsumować wartość. – user2112420

2
void Main() 
{ 
      //Me being lazy in init 
    var foos = new [] 
    { 
     new Foo { Id = 1, Value = 5}, 
     new Foo { Id = 1, Value = 7}, 
     new Foo { Id = 2, Value = 1}, 
     new Foo { Id = 3, Value = 6}, 
     new Foo { Id = 3, Value = 2}, 
    }; 
    foreach(var x in foos) 
    { 
     x.Name = "Name" + x.Id; 
     x.Category = "Category" + x.Id; 
    } 
      //end init. 

    var result = from x in foos 
       group x.Value by new { x.Id, x.Name, x.Category} 
       into g 
       select new { g.Key.Id, g.Key.Name, g.Key.Category, Value = g.Sum()}; 
    Console.WriteLine(result); 
} 

// Define other methods and classes here 
public class Foo 
{ 
    public int Id {get;set;} 
    public int Value {get;set;} 

    public string Name {get;set;} 
    public string Category {get;set;} 
} 
+0

Znam ten sposób, ale nie chcę mieć w mojej grupie tak wielu pól, mam więcej niż 7. – user2112420

+0

@ user2112420 Wtedy będziesz musiał normalizować swoją klasę – Aron

+0

Jest to zapytanie o wynik I rób z wielu tabel i utwórz obiekt tego typu – user2112420

1

spróbuj tego:

var objList = new List<SampleObject>(); 

objList.Add(new SampleObject() { ID = 1, Value = 5, Name = "Name1", Category = "Catergory1"}); 
objList.Add(new SampleObject() { ID = 1, Value = 7, Name = "Name1", Category = "Catergory1"}); 
objList.Add(new SampleObject() { ID = 2, Value = 1, Name = "Name2", Category = "Catergory2"}); 
objList.Add(new SampleObject() { ID = 3, Value = 6, Name = "Name3", Category = "Catergory3"}); 
objList.Add(new SampleObject() { ID = 3, Value = 2, Name = "Name3", Category = "Catergory3"}); 

var newList = from val in objList 
       group val by new { val.ID, val.Name, val.Category } into grouped 
       select new SampleObject() { ID = grouped.ID, Value = grouped.Sum(), Name = grouped.Name, Category = grouped.Category }; 

sprawdzić z LINQPad:

newList.Dump();